Es gibt einige Fragen zu SO, die sich auf das Casting von Lambdas auf std::function
s beziehen, aber ich muss noch eines sehen, das ein Parameter-Pack für die Argumentliste verwendet. Das scheint bei meiner Version von g ++ (7.1.1-4) kaputt zu sein, und möglicherweise wird es einfach nicht unterstützt. Also ist das legal c ++ 17 (im Standard)? Wenn nicht, warum?
Der obige Code wird nicht kompiliert, weil die Typableitung fehlschlägt. Offensichtlich macht das explizite Eingeben von x
als std::function<int (int, int)>
anstelle von auto
den Fehler weg. Aber das erlaubt mir nicht, einen r-Wert an Functor
zu übergeben, wie ich es möchte. Ich möchte auch keine Typsicherheit verlieren, indem ich einen anderen Template-Parameter für den Funktionstyp verwende.
Was ich wirklich nicht verstehe ist, warum der obige Code nicht kompiliert werden kann, aber der folgende Code ist in Ordnung und funktioniert:
%Vor% Das Problem ist, dass der Compiler nicht weiß, dass int, int
die Gesamtheit von TArgs
sein soll, und versucht daher, den Rest von TArgs
vom Argument f
abzuleiten.
Dies wäre beispielsweise gültig:
%Vor% Sie müssen also den Compiler anweisen, nicht den Rest von TArgs
abzuleiten. Zum Beispiel könnten Sie schreiben:
Oder Sie könnten Functor
mit einer nicht zerlegten Signatur Sig
:
Oder Sie könnten die Verwendung von TArgs
im Parameter f
in einem nicht-abgeleiteten Kontext umbrechen:
Dies schlägt fehl:
%Vor%, weil Sie nicht angeben, dass die Gesamtheit von TArgs...
{int, int}
ist. Sie geben an, dass die ersten beiden Typen {int, int}
sind. Wenn wir diese drei Typen zur Verfügung stellen, haben wir das Deduktionsproblem effektiv in folgendes umgewandelt:
Dies wird nicht kompiliert, weil ein Lambda kein std::function
ist (oder von eins abgeleitet ist), was der gleiche Grund ist, warum Sie dies nicht aufgerufen haben könnten, ohne irgendwelche Typen bereitgestellt zu haben.
Die nicht-variadische Version hat dieses Problem nicht, da Sie alle Typen bereitgestellt haben.
Aber wirklich, was Sie wollen, ist:
%Vor% Damit verlieren Sie keine Sicherheit. Es verwendet std::function
, das Typinformationen verliert, da diese Klassenvorlage zum Eingeben von Erase existiert.
Es ist sehr selten eine gute Idee, ein Lambda auf ein std::function
in einem template
zu setzen, wenn Sie es einfach aufrufen. std::function
ist type-erasure, und das Löschen von Templates ist nur dann sinnvoll, wenn Sie es "woanders weitergeben" und / oder zurückgeben.
Versuchen Sie es auf jeden Fall:
%Vor%Aber du solltest es wirklich tun
%Vor%was perfekt typsicher ist.
Wenn Sie eine frühe Typprüfung wünschen, könnten Sie
schreiben %Vor%tue es dann
%Vor%aber nur, wenn Sie wirklich brauchen.
Hier ist eine Lösung, mit der Sie functor
aufrufen können, ohne das Template-Argument anzugeben:
Dies ist nur ein fauler erster Entwurf für den Einstieg. Sie müssen es erweitern, um die Weiterleitung und nicht-const operator()
zu unterstützen.
Es funktioniert in 2 Stufen:
1. Wir haben Fun_trait
who - für Zeiger-Methodentypen (z. B. die operator()
eines Lambda) - einen Alias F
für den erforderlichen std::function
-Argumenttyp definiert.
Als nächstes haben wir eine Überladung Ihrer Funktion functor
, die über SFINAE mit std::void_t
nur für Funktoren mit einem nicht überladenen operator()
(zB ein Lambda) eintritt und dann die oben genannte Eigenschaft verwendet, ruft die Hauptfunktion% auf. co_de% mit dem korrekten Template-Argument abgeleitet.
Tags und Links c++ lambda variadic-templates c++17