Étant donné une capture lambda, quelles règles déterminent les types des membres de fermeture résultants?

Comment puis-je prédire avec précision à partir d’une capture quel type de membre sera créé dans le lambda?

En C ++, je pensais que la capture d’un object de type T par valeur créait un membre de données de type const T , et par référence T& . Mais en compilant ceci:

 #include  struct A{ A(){std::cout<<"A\n";} A(const A&){std::cout< void{ //Fixed: //ra is A, cra is const A, a is A& //lambda is void operator()()const a.cf(); af();//pass //ra.cf(); ra.f();//ra.f compilation err. //cra.cf(); cra.f();//cra.f compilation err }; //f00(); //A&,A& auto f01 = [ra, cra, &a]()mutable-> void{ //Fixed: //ra is A, cra is const A, a is A& //lambda is void operator()()mutalbe a.cf(); af();//pass ra.cf(); ra.f();//pass cra.cf(); cra.f();//cra.cf pass, but cra.f error, why? }; //f01(); //A&,A& auto f02 = [&ra, &cra, &a]()mutable-> void{ //Fixed: //ra is A&, cra is const A&, a is A& //lambda is void operator()()mutable a.cf(); af();//pass ra.cf(); ra.f();//pass //cra.cf(); cra.f();//cra.cf pass, but cra.f error, why? }; f02(); // return 0; } 

J’ai rencontré l’erreur de compilation suivante:

 test_lambda.cpp:26:25: error: passing 'const A' as 'this' argument discards qualifiers [-fpermissive] cra.cf(); cra.f();//pass, cra.f error ^ test_lambda.cpp:8:10: note: in call to 'void A::f()' void f(){} ^ 

Cela signifie-t-il que l’ cra a vraiment été capturé par référence, plutôt que par une copie de l’object référé comme prévu?

Le type des entités capturées rest le même, sauf que les références aux objects sont capturées en tant que copies des objects référencés . De la référence CPP sur les types de fermeture lambda :

Le type de chaque membre de données est le type de l’entité capturée correspondante, sauf si l’entité a un type de référence (dans ce cas, les références aux fonctions sont capturées en tant que références lvalue aux fonctions référencées, et les références aux objects sont capturées en tant que copies du objects référencés).

Dans tous vos lambdas, le type du membre de fermeture cra est A Ils ne sont pas, eux-mêmes, const . Cependant, l’ operator() appel de fonction operator() par défaut du lambda est. L’erreur sur la ligne 17 à propos de f00 est due au fait que vous essayez de modifier un membre de fermeture créé par copy lorsque vous appelez ra.f() , mais étant donné qu’il possède un operator() const , il ne peut effectuer que des opérations const sur son membres.

C’est pourquoi, dans les trois fonctions, l’appel du non- const A::f on cra donne une erreur de compilation. Vous devez append mutable après la liste d’arguments lambda pour permettre l’exécution d’opérations non const sur les membres de fermeture par copie.