Udostępnij za pośrednictwem


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

  • Anonymous
    January 12, 2012
    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);"

  • Anonymous
    January 12, 2012
    JCAB, good catch! The code has been corrected accordingly. Thanks a lot!

  • Anonymous
    February 08, 2012
    The comment has been removed

  • Anonymous
    February 09, 2012
    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