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;
};