restrict(amp) restrictions part 8 of N – restricted lambda expressions

This post assumes and requires that you have read the introductory post to this series which also includes a table of content. With that out of the way let’s look at of restrictions on amp lambda expressions.

Restriction specifiers can be applied to a lambda expression, which will be applied to the function call operator of the generated lambda class. For example the following lambda

Foo ambientVar;

auto functor = [ambientVar] (int y) restrict(amp) -> int { return y + ambientVar.z; };

 

is equivalent to a function object (as discussed previously):

 

Foo ambientVar;

class <LambdaName> {

public:

       <LambdaName>(const Foo& foo): capturedFoo(foo) {}

       ~<LambdaName>(){ }

       int operator()(int y) const restrict(amp) { return y + capturedFoo.z; }

private:

       Foo capturedFoo;

};

<LambdaName> functor(ambientVar);

Note that if there are no explicit restriction specifiers on a lambda expression, the lambda expression inherits restriction specifiers from its ambient context. That is, if a lambda expression is declared inside an amp-restricted function, it’s automatically an amp lambda expression. What’s more, its constructor and destructor are now also amp-restricted because the restriction specifiers applied to a function definition are recursively applied to all functions defined within its body that do not have explicit restriction specifiers. So for a variation of the above example,

void foo() restrict(amp)

{

    Foo ambientVar;

    auto functor = [ambientVar] (int y) -> int { return y + ambientVar.z; };

}

 

The generate lambda class now looks like the following:

 

class <LambdaName> {

public:

    <LambdaName>(const Foo& foo) restrict(amp)

        : capturedFoo(foo) {} // Foo's copy constructor must be restrict(amp) too!

    ~<LambdaName>() restrict(amp) { }

    int operator()(int y) const restrict(amp) { return y + capturedFoo.z; }

private:

    Foo capturedFoo;

};