160 votes

Quel est le type de lambda quand déduit avec "auto" en C++11?

J'ai eu l'impression que, le type d'une expression lambda est un pointeur de fonction. Lorsque j'ai effectué les test suivant, je l'ai trouvé mauvais (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 !
}

Est au-dessus de code manquant ? Si non, alors, qu'est-ce que l' typeof d'une expression lambda quand déduit auto mot-clé ?

166voto

jalf Points 142628

Le type d'une expression lambda est indéterminé.

Mais ils sont en général de simples sucre syntaxique pour les foncteurs. Un lambda se traduit directement par un foncteur. Rien à l'intérieur de l' [] sont transformés en paramètres du constructeur et les membres du foncteur de l'objet, et les paramètres à l'intérieur d' () sont activées dans les paramètres pour le foncteur de l' operator().

Un lambda qui capte l'absence de variables (rien à l'intérieur de l' []s') peut être converti en un pointeur de fonction (MSVC2010 ne supporte pas cela, si c'est votre compilateur, mais cette conversion est la partie de la norme).

Mais le type réel de l'lambda n'est pas un pointeur de fonction. C'est une quelconque foncteur type.

120voto

avakar Points 20031

C'est un unique sans nom de la structure qui les surcharges de l'opérateur d'appel de fonction. Chaque instance d'un lambda introduit un nouveau type.

Dans le cas particulier d'un non-capture lambda, la structure en plus a une conversion implicite d'un pointeur de fonction.

27voto

[C++11: 5.1.2/3]: Le type de la lambda-expression (qui est aussi le type de la fermeture de l'objet) est un unique, sans nom non-union type de classe qu'on appelle la fermeture type - dont les propriétés sont décrites ci-dessous. Ce type de classe n'est pas un agrégat (8.5.1). La fermeture est de type déclaré dans le plus petit bloc de portée, l'étendue de classe, ou de l'espace de champ qui contient le correspondant de la lambda-expression. [..]

La clause énumère diverses propriétés de ce type. Voici quelques faits saillants:

[C++11: 5.1.2/5]: À la fermeture pour un type lambda-expression a un public inline appel de fonction de l'exploitant (13.5.4) dont les paramètres et le type de retour sont décrites par le lambda-expression's paramètre-déclaration de la clause et de fuite-retour-type respectivement. [..]

[C++11: 5.1.2/6]: À la fermeture pour un type lambda-expression avec pas de lambda-capture a un public de non-virtuel non-explicite const fonction de conversion de pointeur de fonction ayant le même paramètre et les types de retour de la fermeture du type de la fonction d'appel de l'opérateur. La valeur retournée par cette fonction de conversion doit être l'adresse d'une fonction qui, lorsqu'il est appelé, a le même effet que l'invocation de la fermeture du type de la fonction d'appel de l'opérateur.

La conséquence de ce dernier passage, c'est que, si vous avez utilisé une conversion, vous serez en mesure d'attribuer LAMBDA de pFptr.

6voto

BЈовић Points 28674
#include <iostream>
#include <typeinfo>

#define LAMBDA [] (int i)->long { return 0l; }
int main ()
{
  long (*pFptr)(int) = LAMBDA;  // ok
  auto pAuto = LAMBDA;  // ok

  std::cout<<typeid( *pAuto ).name() << std::endl;
  std::cout<<typeid( *pFptr ).name() << std::endl;

  std::cout<<typeid( pAuto ).name() << std::endl;
  std::cout<<typeid( pFptr ).name() << std::endl;
}

Les types de fonctions sont en effet les mêmes, mais le lambda introduit un nouveau type (comme un foncteur).

0voto

Gabriel Points 858

Une solution pratique de Comment puis-je stocker un boost::bind objet en tant que membre de la classe?, essayez boost::function<void(int)> ou std::function<void(int)>.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X