Passer lambda déclaré en utilisant mot-clé auto par référence non-const comme argument du type de paramètre std :: function

Considérons le code suivant:

#include  #include  // passing function object by value void foo(std::function f) { std::cout << f(3, 7) << std::endl; } // passing const function object by reference void bar(const std::function & f) { std::cout << f(3, 7) << std::endl; } // passing non-const function object by reference void fizz(std::function & f) { std::cout << f(3, 7) << std::endl; } int main() { std::function g1 = [] (int x, int y) { return x * y; }; auto g2 = [] (int x, int y) { return x * y; }; foo(g1); // OK foo(g2); // OK bar(g1); // OK bar(g2); // OK fizz(g1); // OK // comstack error: // error: invalid initialization of reference of type // 'std::function&' from expression of type // 'main()::' // error: in passing argument 1 of 'void fizz(std::function&)' fizz(g2); } 

Quelqu’un pourrait-il m’expliquer:

(a) Pourquoi fizz(g2) génère une erreur de compilation et non les autres constructions? Il semble que je puisse passer un lambda par référence si je tape explicitement son type dans sa déclaration, mais pas si j’utilise le mot clé auto , OU si je déclare le type de paramètre de fonction comme étant const .

(b) Que signifie const dans le type de paramètre de fonction ici?

(c) Dans quelles circonstances préférerais-je passer par valeur plutôt que référence? (UPDATE: maintenant une question distincte: C ++ 11: object fonction pass (lambda ou autre) par référence ou valeur? )?

Merci pour toute idée.

Dans votre cas fizz(g1) , g1 est déjà une std::function . Par conséquent, une conversion implicite n’est pas nécessaire. Le paramètre fizz So est donc une référence non constante à g1 .

Dans fizz(g2) , g2 n’est pas une std::function . Par conséquent, le compilateur doit effectuer une conversion implicite. Et la conversion implicite renvoie un temporaire .

Les objects temporaires ne peuvent pas être liés à des références non constantes; ils ne peuvent se lier qu’à des références ou des valeurs const . D’où l’erreur du compilateur.

Que signifie const dans le type de paramètre de fonction ici?

Vous pouvez uniquement appeler les membres const de l’object, vous ne pouvez pas le convertir implicitement en non- const et vous ne pouvez pas effectuer d’opérations non const sur ses membres.

Vous savez, comme toute autre utilisation de const .

De manière générale, quand une fonction prend un paramètre par référence non-const, elle dit quelque chose de très spécial sur ce qu’elle compte faire avec ce paramètre. C’est-à-dire que vous lui donnez un object et qu’il va faire des choses non constantes avec lui (c’est-à-dire: modifier cet object). C’est pourquoi les temporaires ne se lient pas à des références non constantes; ce sera probablement une erreur de l’utilisateur, car le temporaire peut ne pas mettre à jour l’object original que vous avez transmis.

À moins que fizz ne modifie réellement l’object, vous devez le transmettre soit par valeur, soit par const& .