2017-03-15 2 views
1

Avec une fonction, on peut écrire:Transfert parfait dans un lambda?

template <class T> void f(T&& x) {myfunction(std::forward<T>(x));} 

mais avec un lambda, nous n'avons T:

auto f = [](auto&& x){myfunction(std::forward</*?*/>(x));} 

Comment faire parfait-transfert dans un lambda? Est-ce que decltype(x) fonctionne comme type dans std::forward?

Répondre

4

La façon canonique de transmettre un argument lambda qui a été lié à une référence de transfert est en effet avec decltype:

auto f = [](auto&& x){ 
    myfunction(std::forward<decltype(x)>(x)); 
} //      ^^^^^^^^^^^ 
+1

Il existe une [proposition pour C++ 2a] (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0428r0.pdf) pour créer des lambdas avec des modèles d'opérateur d'appel un peu plus facile à écrire. –

+0

Lien intéressant. Cela ne vaudrait-il pas la peine de mettre le lien directement dans la réponse? – skypjack

+0

@skypjack: Étant donné la nature ténue et spéculative des premières propositions, et le fait que la question concerne le C++ 14, j'ai pensé qu'il valait mieux laisser un commentaire. Peut-être qu'une fois la décision prise, nous pourrons mettre à jour ceci (juillet?). –

2

Mon idiome préféré pour cela est:

auto f = [](auto&& x){myfunction(decltype(x)(x));} 

que je lis comme " x comme le type x a été déclaré comme ".

Pour voir comment cela fonctionne, examinez ce qui se passe lorsque x est un int&&. decltype(x)(x) est (int&&)(x), ce qui produit une référence rvalue à x. Si x est un int&, alors nous obtenons (int&)(x) qui est un cast noop à une référence. Rappelez-vous, decltype(x) inclut la catégorie de référence.

Maintenant, pour les paramètres est plus courte, mais auto&& équivalent à:

auto f = [](auto&& x){myfunction(std::forward<decltype(x)>(x));} 

l'alternative.

Pour auto paramètres:

auto f = [](auto x){myfunction(decltype(x)(x));} 

il induit une copie supplémentaire, tandis que

auto f = [](auto x){myfunction(std::forward<decltype(x)>(x));} 

au lieu de se déplace-x.

Alors que je traite habituellement de style C jette comme étant trop dangereux, decltype(x)(x) peut, au pire, faire une copie de type correct de x si x n'est pas une variable auto&&. Et il y a quelque chose à dire pour la brièveté de celui-ci.

+0

La distribution decltype est une bonne astuce, mais ce que j'aime dans 'std :: forward', c'est qu'elle crée une indication lisible (et greppable) que le transfert est en cours et qu'un' && 'proche est une référence de transfert . –

+0

Je suis d'accord sur celui-là; la concision vient au prix de la signification, OMI. Beau tour cependant, +1! – Columbo

+0

Pourriez-vous élaborer avec un exemple où la copie est faite? pour les paramètres 'auto': ... e.g.'int a; f (a); '->' auto == int', première copie quand 'auto x' est initialisé (probablement optimisé), puis dans le premier cas: copie à cause de' int (x) '(certainement optimisé dans le second cas: un déplacement (si myFunction est implémenté en tant que tel) car std :: forward envoie 'int &&'. Est-ce exact? – Gabriel