J'avais une perception que, le type d'un lambda est un pointeur de fonction. Lorsque j'ai effectué le test suivant, j'ai trouvé que c'était faux ( démo ).
#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 !
}
Le code ci-dessus manque-t-il un point? Sinon, qu'est-ce que l' typeof
expression a lambda lorsqu'elle est déduite avec un auto
mot-clé?
Réponses:
Le type d'une expression lambda n'est pas spécifié.
Mais ce ne sont généralement que du sucre syntaxique pour les foncteurs. Un lambda est traduit directement en foncteur. Tout ce qui se trouve à l'intérieur de
[]
est transformé en paramètres de constructeur et membres de l'objet foncteur, et les paramètres à l'intérieur()
sont transformés en paramètres pour le foncteuroperator()
.Un lambda qui ne capture aucune variable (rien à l'intérieur du
[]
's) peut être converti en un pointeur de fonction (MSVC2010 ne le prend pas en charge, si c'est votre compilateur, mais cette conversion fait partie du standard).Mais le type réel du lambda n'est pas un pointeur de fonction. C'est un type de foncteur non spécifié.
la source
operator()
essentiellement stackoverflow.com/questions/356950/c-functors-and-their-usesIl s'agit d'une structure unique sans nom qui surcharge l'opérateur d'appel de fonction. Chaque instance d'un lambda introduit un nouveau type.
Dans le cas particulier d'un lambda non capturant, la structure a en plus une conversion implicite en un pointeur de fonction.
la source
type_info::name()
est défini par l'implémentation, il peut donc renvoyer n'importe quoi. En pratique, le compilateur nommera le type pour le bien de l'éditeur de liens.La clause continue en listant les différentes propriétés de ce type. Voici quelques faits saillants:
La conséquence de ce dernier passage est que, si vous utilisiez une conversion, vous pourrez attribuer
LAMBDA
àpFptr
.la source
Les types de fonction sont en effet les mêmes, mais le lambda introduit un nouveau type (comme un foncteur).
la source
__PRETTY_FUNCTION__
, comme danstemplate<class T> const char* pretty(T && t) { return __PRETTY_FUNCTION__; }
, et dépouille le supplément s'il commence à être encombré. Je préfère voir les étapes indiquées dans la substitution de modèle. Si vous manquez__PRETTY_FUNCTION__
, il existe des alternatives pour MSVC, etc., mais les résultats dépendent toujours du compilateur pour la même raison que CXXABI est nécessaire.Il convient également de noter que lambda est convertible en pointeur de fonction. Cependant typeid <> renvoie un objet non-trvial qui devrait différer du pointeur lambda au pointeur de fonction générique. Le test pour typeid <> n'est donc pas une hypothèse valide. En général, C ++ 11 ne veut pas que nous nous préoccupions de la spécification de type, tout ce qui compte si un type donné est convertible en type cible.
la source
Une solution pratique de Comment puis-je stocker un objet boost :: bind en tant que membre de classe? , essayez
boost::function<void(int)>
oustd::function<void(int)>
.la source