Ich hatte die Auffassung, dass der Typ eines Lambda ein Funktionszeiger ist. Als ich den folgenden Test durchführte, stellte ich fest, dass er falsch war ( Demo ).
#define LAMBDA [] (int i) -> long { return 0; }
int main ()
{
long (*pFptr)(int) = LAMBDA; // ok
auto pAuto = LAMBDA; // ok
assert(typeid(pFptr) == typeid(pAuto)); // assertion fails !
}
Fehlt dem obigen Code ein Punkt? Wenn nicht, was ist der typeof
Lambda-Ausdruck, wenn er mit dem auto
Schlüsselwort abgeleitet wird ?
Antworten:
Der Typ eines Lambda-Ausdrucks ist nicht spezifiziert.
Aber sie sind im Allgemeinen nur syntaktischer Zucker für Funktoren. Ein Lambda wird direkt in einen Funktor übersetzt. Alles innerhalb des
[]
wird in Konstruktorparameter und Elemente des Funktorobjekts umgewandelt, und die darin enthaltenen Parameter()
werden in Parameter für den Funktor umgewandeltoperator()
.Ein Lambda, das keine Variablen erfasst (nichts in den
[]
's), kann in einen Funktionszeiger konvertiert werden (MSVC2010 unterstützt dies nicht, wenn dies Ihr Compiler ist, diese Konvertierung jedoch Teil des Standards ist).Der tatsächliche Typ des Lambda ist jedoch kein Funktionszeiger. Es ist ein nicht spezifizierter Funktortyp.
quelle
operator()
im Grunde stackoverflow.com/questions/356950/c-functors-and-their-usesEs ist eine eindeutige unbenannte Struktur, die den Funktionsaufrufoperator überlastet. Jede Instanz eines Lambda führt einen neuen Typ ein.
Im Sonderfall eines nicht erfassenden Lambdas hat die Struktur zusätzlich eine implizite Konvertierung in einen Funktionszeiger.
quelle
type_info::name()
ist implementierungsdefiniert, sodass alles zurückgegeben werden kann. In der Praxis benennt der Compiler den Typ für den Linker.In der Klausel werden verschiedene Eigenschaften dieses Typs aufgelistet. Hier einige Highlights:
Die Folge dieser letzten Passage ist , dass, wenn Sie eine Konvertierung verwendet, die Sie zuweisen wären in der Lage
LAMBDA
zupFptr
.quelle
Die Funktionstypen sind zwar gleich, aber das Lambda führt einen neuen Typ ein (wie ein Funktor).
quelle
__PRETTY_FUNCTION__
wie intemplate<class T> const char* pretty(T && t) { return __PRETTY_FUNCTION__; }
und ziehe das Extra aus, wenn es überfüllt wird. Ich ziehe es vor, die in der Vorlagenersetzung gezeigten Schritte zu sehen. Wenn Sie fehlen__PRETTY_FUNCTION__
, gibt es Alternativen für MSVC usw., aber die Ergebnisse sind immer vom Compiler abhängig, aus dem gleichen Grund, aus dem CXXABI erforderlich ist.Es sollte auch beachtet werden, dass Lambda in einen Funktionszeiger konvertierbar ist. Typeid <> gibt jedoch ein nicht-trviales Objekt zurück, das sich von Lambda zu generischem Funktionszeiger unterscheiden sollte. Der Test für typeid <> ist also keine gültige Annahme. Im Allgemeinen möchte C ++ 11 nicht, dass wir uns um die Typspezifikation kümmern, alles was wichtig ist, wenn ein bestimmter Typ in einen Zieltyp konvertierbar ist.
quelle
Eine praktische Lösung von Wie kann ich ein boost :: bind-Objekt als Klassenmitglied speichern? versuchen
boost::function<void(int)>
oderstd::function<void(int)>
.quelle