Does the C ++ specification provide a closure implementation by passing stack address offsets?

I do not have access to the C ++ language specification at the moment, but the unauthorized website cppreference.com says:

http://en.cppreference.com/w/cpp/language/lambda

The lambda expression constructs an unnamed temporary object prvalue of a unique unnamed unrelated non-aggregate type, known as a closure type.

I know that the specification also states that only non-exciting lambdas can decompose into function pointers (copied from Positive lambda: '+ [] {}' - What witchcraft is this? ):

The closure type for a lambda expression without lambda capture has a public non-virtual implicit conversion function const, so that a pointer to a function that has the same parameter and return types as the closure function call statement. The value returned by this conversion function must be the address of a function that, when called, has the same effect as when calling the statement to call the close function.

In C # and C ++, the lambda method with variable capture (i.e. closure) looks like this when used (warning: C # / C ++ style pseudo-code) in front):

class Foo {

    void AConventionalMethod() {

        String x = null;
        Int32 y = 456;

        y = this.arrayOfStringsField.IndexOfFirstMatch( (element, index) => {
            x = this.DoSomethingWithAString( element );
            y += index;
            return index > 5; // bool return type
        } );
    }
}

This can be considered roughly equivalent:

class Closure {

    Foo foo;
    String x;
    Int32 y;

    Boolean Action(String element, Int32 index) {
        this.x = this.foo.DoSomethingwithAString( element );
        this.y += index;
        return index > 5;
    }
}

class Foo {

    void AConventionalMethod() {

        String x = null;
        Int32 y = 456;

        {
            Closure closure = new Closure() { foo = this, x = x, y = y };
            Int32 tempY = this.arrayOfStringsField.IndexOfFirstMatch( closure.Action ); // passes `closure` as `this` inside the Delegate
            x = closure.x;
            y = closure.y;
            y = tempY;
        }
    }
}

/ this Closure::Action. #, Delegate , this, ++ , std::function ( , this) - - C- , , this.

, - , - - - . , this -saving Delegate std::function, :

void AConventionalMethod() {

    void* frame;
    frame = &frame; // get current stack frame 'base address'

    string x = nullptr;
    int32_t y = 456;

    y = this.arrayOfStrings( lambdaAction );
}

static bool lambdaAction(void* frame, string element, int32_t index) {

    Foo* foo = reintepret_cast<Foo*>( frame + 0 );
    string* x = reintepret_cast<string*>( frame + 4 ); // the compiler would know what the `frame + n` offsets are)
    int32_t* y = reintepret_cast<int32_t*>( frame + 8 );

    *x = foo->doSomethingWithAString( element );
    *y = *y + index;
    return index > 5;
}

: , , , Closure , - lambdaAction - (ab) .

, , , : , , -, . , ( , ):

void AConventionalMethod() {

    void* frame;
    frame = &frame;

    String x = null;
    Int32 y = 456;

    // the below code would actually be generated by the compiler:
    char wrapper[] = __asm {
        push frame         ; does not alter any existing arguments
                           ; but pushes/adds 'frame' as a new
                           ; argument, and in a right-to-left calling-
                           ; convention order this means that 'frame'
                           ; becomes the first argument for 'lambdaAction'
        call lambdaAction
        return             ; EAX return value preserved
    };

    y = a_higher_order_function_with_C_style_function_pointer_parameter( wrapper ); // a
}

static bool lambdaAction(void* frame, string element, int32_t index) {
    // same as previous example lambdaAction
}

wrapper (, AConventionalMethod), , .

:

, - - , - , ++ lambdas, C-style, , ? ( , )?

+4
1

++ , : operator(), .

, , , . lambdas ++.

. . .

, ++ , ; , . , , . , , . , ( , ).


, ++, - . this . , , , ( ), .

++ . "" , . ++, . , ; , , , .

+6

Source: https://habr.com/ru/post/1686284/


All Articles