Étant donné un lambda, est-il possible de déterminer son type de paramètre et son type de retour? Si oui, comment?
Fondamentalement, je veux lambda_traits
ce qui peut être utilisé des manières suivantes:
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
La motivation derrière est que je veux utiliser lambda_traits
dans un modèle de fonction qui accepte un lambda comme argument, et j'ai besoin de connaître son type de paramètre et son type de retour dans la fonction:
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!
//...
}
Pour le moment, nous pouvons supposer que le lambda prend exactement un argument.
Au départ, j'ai essayé de travailler avec std::function
comme:
template<typename T>
A<T> f(std::function<bool(T)> fun)
{
return A<T>(fun);
}
f([](int){return true;}); //error
Mais cela donnerait évidemment une erreur. Je l'ai donc changé en TLambda
version du modèle de fonction et je souhaite construire l' std::function
objet à l'intérieur de la fonction (comme indiqué ci-dessus).
Réponses:
Drôle, je viens d'écrire une
function_traits
implémentation basée sur Spécialiser un modèle sur un lambda en C ++ 0x qui peut donner les types de paramètres. L'astuce, comme décrit dans la réponse à cette question, consiste à utiliser le des lambda .decltype
operator()
Notez que cette solution ne fonctionne pas pour lambda générique comme
[](auto x) {}
.la source
tuple_element
, merci.const
, pour ceux déclarés par lambdamutable
([]() mutable -> T { ... }
).operator()
pas avec cette implémentation.auto
n'est pas un type, donc ça ne peut jamais être la réponse àtraits::template arg<0>::type
Bien que je ne sois pas sûr que ce soit strictement conforme à la norme, ideone a compilé le code suivant:
Cependant, cela ne fournit que le type de fonction, de sorte que le résultat et les types de paramètres doivent en être extraits. Si vous pouvez utiliser
boost::function_traits
,result_type
etarg1_type
répondra à l'objectif. Comme ideone ne semble pas fournir de boost en mode C ++ 11, je n'ai pas pu publier le code réel, désolé.la source
La méthode de spécialisation présentée dans la réponse de @KennyTM peut être étendue pour couvrir tous les cas, y compris les lambdas variadiques et mutables:
Démo .
Notez que l'arité n'est pas ajustée pour les variadiques
operator()
. Au lieu de cela, on peut également envisageris_variadic
.la source
La réponse fournie par @KennyTMs fonctionne très bien, cependant si un lambda n'a pas de paramètres, l'utilisation de l'index arg <0> ne compile pas. Si quelqu'un d'autre avait ce problème, j'ai une solution simple (plus simple que d'utiliser des solutions liées à SFINAE, c'est-à-dire).
Ajoutez simplement void à la fin du tuple dans la structure arg après les types d'arguments variadiques. c'est à dire
comme l'arité ne dépend pas du nombre réel de paramètres du modèle, le réel ne sera pas incorrect, et s'il est égal à 0, au moins arg <0> existera toujours et vous pourrez en faire ce que vous voudrez. Si vous prévoyez déjà de ne pas dépasser l'index,
arg<arity-1>
cela ne devrait pas interférer avec votre implémentation actuelle.la source