c++ - Lambda-Schließungswerte können als r-Wert-Referenzparameter übergeben werden




closures c++14 (2)

Ich fand heraus, dass lvalue Lambda-Closures immer als rvalue Funktionsparameter übergeben werden können.

Siehe die folgende einfache Demonstration.

#include <iostream>
#include <functional>

using namespace std;

void foo(std::function<void()>&& t)
{
}

int main()
{
    // Case 1: passing a `lvalue` closure
    auto fn1 = []{};
    foo(fn1);                          // works

    // Case 2: passing a `lvalue` function object
    std::function<void()> fn2 = []{};
    foo(fn2);                          // compile error

    return 0;
}

Fall 2 ist das Standardverhalten (ich habe gerade eine std::function zu Demonstrationszwecken verwendet, aber jeder andere Typ würde sich genauso verhalten).

Wie und warum funktioniert Fall 1? Wie ist der Zustand des Schließens von fn1 nach der Rückkehr der Funktion?


Wie ist der Zustand des Schließens von fn1 nach der Rückkehr der Funktion?

fn1 ist zustandslos, da es nichts erfasst.

Wie und warum funktioniert Fall 1?

Dies funktioniert, weil das Argument einen anderen Typ hat als der Typ, auf den rvalue verweist. Aufgrund eines anderen Typs werden implizite Konvertierungen berücksichtigt. Da das Lambda für die Argumente dieser std::function aufrufbar ist, kann es implizit über den Template-Konvertierungskonstruktor der std::function dieses Lambda konvertiert std::function . Das Ergebnis der Konvertierung ist ein Wert und kann daher mit der rWert-Referenz verknüpft werden.


Wie und warum funktioniert Fall 1?

Das Aufrufen von foo erfordert eine Instanz von std::function<void()> , die an eine rWert-Referenz gebunden ist . std::function<void()> kann aus jedem aufrufbaren Objekt erstellt werden , das mit der Signatur void() kompatibel ist.

Zunächst wird ein temporäres std::function<void()> -Objekt aus []{} . Der hier verwendete Konstruktor ist # 5, der den Abschluss in die std::function Instanz kopiert:

template< class F >
function( F f );

Initialisiert das Ziel mit std::move(f) . Wenn f ein Nullzeiger auf function oder ein Nullzeiger auf member ist, *this nach dem Aufruf leer.

Dann wird die temporäre function an die rWertreferenz gebunden.

Wie ist der Zustand des Schließens von fn1 nach der Rückkehr der Funktion?

Dasselbe wie zuvor, da es in eine std::function Instanz kopiert wurde. Der Originalverschluss bleibt davon unberührt.





rvalue-reference