Ist es bei einem Lambda möglich, den Parametertyp und den Rückgabetyp herauszufinden? Wenn ja, wie?
Grundsätzlich möchte ich, lambda_traits
welche auf folgende Arten verwendet werden kann:
auto lambda = [](int i) { return long(i*10); };
lambda_traits<decltype(lambda)>::param_type i; //i should be int
lambda_traits<decltype(lambda)>::return_type l; //l should be long
Die Motivation dahinter ist, dass ich lambda_traits
in einer Funktionsvorlage verwenden möchte, die ein Lambda als Argument akzeptiert, und ich muss den Parametertyp und den Rückgabetyp innerhalb der Funktion kennen:
template<typename TLambda>
void f(TLambda lambda)
{
typedef typename lambda_traits<TLambda>::param_type P;
typedef typename lambda_traits<TLambda>::return_type R;
std::function<R(P)> fun = lambda; //I want to do this!
//...
}
Wir können vorerst davon ausgehen, dass das Lambda genau ein Argument hat.
Anfangs habe ich versucht, mit folgenden Elementen zu arbeiten std::function
:
template<typename T>
A<T> f(std::function<bool(T)> fun)
{
return A<T>(fun);
}
f([](int){return true;}); //error
Aber es würde offensichtlich Fehler geben. Also habe ich es in die TLambda
Version der Funktionsvorlage geändert und möchte das std::function
Objekt innerhalb der Funktion erstellen (wie oben gezeigt).
Antworten:
Komisch, ich habe gerade eine
function_traits
Implementierung geschrieben , die auf der Spezialisierung einer Vorlage auf einem Lambda in C ++ 0x basiert und die Parametertypen angeben kann. Der Trick, wie in der Antwort in dieser Frage beschrieben, besteht darin, den Lambda zu verwenden .decltype
operator()
Beachten Sie, dass diese Lösung nicht für generisches Lambda wie funktioniert
[](auto x) {}
.quelle
tuple_element
nachgedacht, danke.const
, für das deklarierte Lambdamutable
([]() mutable -> T { ... }
) verwenden.operator()
, die bei dieser Implementierung nicht vorhanden sind.auto
ist kein Typ, also kann es nie die Antwort auf seintraits::template arg<0>::type
Obwohl ich nicht sicher bin, ob dies streng standardkonform ist, hat ideone den folgenden Code kompiliert:
Dies liefert jedoch nur den Funktionstyp, sodass die Ergebnis- und Parametertypen daraus extrahiert werden müssen. Wenn Sie verwenden können
boost::function_traits
,result_type
undarg1_type
den Zweck erfüllen. Da ideone im C ++ 11-Modus keinen Boost zu bieten scheint, konnte ich den eigentlichen Code leider nicht veröffentlichen.quelle
Die in der Antwort von @KennyTMs gezeigte Spezialisierungsmethode kann auf alle Fälle ausgedehnt werden, einschließlich variadischer und veränderlicher Lambdas:
Demo .
Beachten Sie, dass die Arität nicht für verschiedene Werte angepasst ist
operator()
. Stattdessen kann man auch überlegenis_variadic
.quelle
Die Antwort von @KennyTMs funktioniert hervorragend. Wenn ein Lambda jedoch keine Parameter hat, wird die Verwendung des Indexarguments <0> nicht kompiliert. Wenn jemand anderes dieses Problem hatte, habe ich eine einfache Lösung (einfacher als die Verwendung von SFINAE-bezogenen Lösungen).
Fügen Sie am Ende des Tupels in der Argumentstruktur nach den variadischen Argumenttypen einfach void hinzu. dh
Da die Arität nicht von der tatsächlichen Anzahl der Vorlagenparameter abhängt, ist die tatsächliche nicht falsch. Wenn sie 0 ist, ist mindestens arg <0> noch vorhanden, und Sie können damit tun, was Sie wollen. Wenn Sie bereits vorhaben, den Index nicht zu überschreiten
arg<arity-1>
, sollte dies Ihre aktuelle Implementierung nicht beeinträchtigen.quelle