Est-il possible de déterminer le type de paramètre et le type de retour d'une lambda?
Donné un lambda, est-il possible de figure, c'est le type de paramètre et le type de retour? Si oui, comment?
Fondamentalement, je veux lambda_traits
qui peut être utilisé dans une 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, c'est que je veux utiliser lambda_traits
dans un modèle de fonction qui accepte un lambda comme argument, et j'ai besoin de savoir c'est le type de paramètre et le type de retour à l'intérieur de 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.
D'abord, 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 il n'aurait évidemment donner d'erreur. Donc je l'ai changé pour TLambda
version de la fonction de modèle et souhaitez construire la std::function
objet à l'intérieur de la fonction (voir ci-dessus).
- Si vous connaissez le type de paramètre alors this peut être utilisé pour déterminer le type de retour. Je ne sais pas comment faire pour déterminer le type de paramètre que.
- Il est supposé que la fonction prend un seul argument ?
- "type de paramètre" Mais arbitraire en fonction lambda n'a pas un type de paramètre. Il peut prendre n'importe quel nombre de paramètres. De sorte que toute classe de traits devraient être conçues pour les paramètres de la requête par la position des indices.
- Oui. pour le moment, nous pouvons supposer que.
- Pour le moment, nous pouvons supposer que le lambda prend exactement un argument.
- "La motivation, c'est que je veux utiliser lambda_traits dans un modèle de fonction qui accepte un lambda comme argument" Pourquoi voudriez-vous qu'il n'accepte qu'un lambda? Ne serait-il pas plus logique de simplement utiliser un
std::function
? Voulez-vous vraiment à forcer l'utilisateur à ne jamais appeler ce avec en particulier une lambda foncteur? - Parce que
std::function
ne semble pas fonctionner: ideone.com/E1Iqf
Vous devez vous connecter pour publier un commentaire.
Drôle, je viens d'écrire un
function_traits
de la mise en œuvre basé sur Spécialisée d'un modèle sur un lambda dans C++0x , qui peut donner les types de paramètres. Le truc, comme indiqué dans la réponse à cette question, est d'utiliser ledecltype
de la lambdaoperator()
.Noter que cette solution ne pas de travail génériques pour le lambda comme
[](auto x) {}
.tuple_element
bien, merci.get_nth_element
méta-fonction, au lieu de (ab)à l'aide detuple_element
.const
, pour ceux lambda déclaréemutable
([]() mutable -> T { ... }
).typedef ReturnType(simple_function_type)(Args...)
dans le function_traits classe. Et aussi, peut-êtretypedef std::function<simple_function_type> std_function_type;
[](auto i)
. Les états d'erreur pour msvc2015:error C3556: 'ttt::<lambda_ff3930f11af2faf2c0b2ac7ad388c762>::operator ()': incorrect argument to 'decltype'
ou clang4.0:reference to overloaded function could not be resolved
. Je sais que c'est légitime d'erreur, mais même si l'arité est pas accessible à cause de l'erreur.operator()
pas à cette mise en œuvre.auto
n'est pas un type, donc il ne peut pas toujours être la réponse àtraits::template arg<0>::type
struct functor { void operator()(int) {}; void operator()(int, double, bool) {} };
?[](auto i)
l'arité est connu, parce que vous avez un seul opérateur avec des arguments basés sur des modèles et vous ne pouvez toujours pas obtenir la quantité. Et même plus, vous avez pour vérifier l'objet sur callability, avant d'accéder à l'arité, ainsi décrit les traits de mise en œuvre n'est pas suffisant dans ce cas.i
sera déduit comme plusieurs types. La classe de synthèse aura plusieurs surcharges deoperator()
. Je ne connais pas de méthode de trouver si tous les surcharges d'une fonction donnée ont le même arité, qui est ce que vous auriez besoin.Si je ne suis pas sûr que c'est strictement la norme conforme à la
ideone compilé le code suivant:
Cependant, elle ne donne que le type de fonction, de sorte que le résultat et les paramètres
les types doivent être extraites.
Si vous pouvez utiliser
boost::function_traits
,result_type
etarg1_type
permettra de répondre à la demande.
Depuis ideone ne semble pas fournir de pouce en C++11 mode, je ne pouvais pas poster
le code, désolé.
La spécialisation de la méthode indiquée dans la @KennyTMs réponse peut être étendue pour couvrir tous les cas, y compris les variadic et mutable lambdas:
Démo.
Noter que l'arité n'est pas ajusté pour variadic
operator()
s. Au lieu de cela on peut aussi envisageris_variadic
.La réponse fournie par @KennyTMs fonctionne très bien, cependant, si un lambda n'a pas de paramètres, à l'aide de l'indice arg<0> ne compile pas. Si quelqu'un d'autre a avoir ce problème, j'ai une solution simple (plus simple que d'utiliser SFINAE solutions connexes, qui est).
Ajoutez simplement nul à la fin du n-uplet dans l'arg struct après les variadic types d'argument. c'est à dire
depuis l'arité n'est pas dépendant du nombre de paramètres du modèle, le réel ne sera pas incorrect, et si c'est 0, alors au moins arg<0> existe toujours et vous pouvez en faire ce que vous voulez. Si vous avez déjà l'intention de ne pas dépasser l'indice de
arg<arity-1>
alors il ne devrait pas interférer avec votre mise en œuvre.