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;

};

Comments (4)

  1. JCAB says:

    This is all awesome, thanx!

    Corrections, though:

    1- In "int operator()(int y) restrict(amp) { return y + ambientVar.z; }", you do mean to say "capturedFoo" instead of "ambientVar". (two instances of this)

    2- In "<LambdaName> functor;" you forgot to provide the initialization for "capturedFoo", which would be "<LambdaName> functor(ambientVar);"

  2. LingliZhang says:

    JCAB, good catch! The code has been corrected accordingly. Thanks a lot!

  3. Arne Mertz says:

    You write that Foo's copy-Ctor has to be restricted(amp) for the restricted(amp) Lambda. Am I right assuming that Foo's Destructor has to be restricted(amp), too?

    Another Question regarding the restricted(amp) Copy-Ctor: is it possible, to have the restricted(amp) Copy-Ctor overloaded with a restricted(cpu) Copy-Ctor?

  4. SteveDeitz says:

    Yes, in the lambda functor, the destructor is restrict(amp) too, and it has to be.

    For your second question, the answer is yes.  You can overload the copy constructor based on the restriction specifier just like any other function.

    Thanks for the good questions.

    Steve

Skip to main content