Dans C ++ 14, l' decltype(auto)
idiome est introduit.
En règle générale, son utilisation est d' autoriser les auto
déclarations à utiliser les decltype
règles sur l'expression donnée .
En recherchant des exemples de "bonne" utilisation de l'idiome, je ne peux penser qu'à des choses comme celles-ci (par Scott Meyers ), à savoir la déduction du type de retour d'une fonction :
template<typename ContainerType, typename IndexType> // C++14
decltype(auto) grab(ContainerType&& container, IndexType&& index)
{
authenticateUser();
return std::forward<ContainerType>(container)[std::forward<IndexType>(index)];
}
Y a-t-il d'autres exemples où cette nouvelle fonctionnalité de langage est utile?
decltype(auto)
pour quelque chose qui ressemble àtemplate<class U, V> decltype(auto) first(std::pair<U, V>& p) { return p.first; }
, bien que je me sois alors rendu compte que je devais utiliserreturn (p.first);
ce qui fonctionne étonnamment (mais IIRC c'est même prévu).decltype(auto)
peut entraîner la copie / le déplacement de quelque chose dans l'objet déclaré, contrairement aux attentes.Réponses:
Transfert de type de retour en code générique
Pour le code non générique, comme l'exemple initial que vous avez donné, vous pouvez sélectionner manuellement pour obtenir une référence comme type de retour:
mais en code générique, vous voulez pouvoir transmettre parfaitement un type de retour sans savoir si vous avez affaire à une référence ou à une valeur.
decltype(auto)
vous donne cette capacité:Retarder la déduction du type de retour dans les modèles récursifs
Dans ce Q&A il y a quelques jours, une récursion infinie lors de l'instanciation du modèle a été rencontrée lorsque le type de retour du modèle a été spécifié comme
decltype(iter(Int<i-1>{}))
au lieu dedecltype(auto)
.decltype(auto)
est utilisé ici pour retarder la déduction du type de retour une fois que la poussière de l'instanciation du modèle s'est déposée.Autres utilisations
Vous pouvez également utiliser
decltype(auto)
dans d'autres contextes, par exemple le projet de norme N3936 stipule également7.1.6.4 spéci fi cateur automatique [dcl.spec.auto]
Le brouillon contient également cet exemple d'initialisation de variable:
la source
(i)
vs esti
-il nouveau dans C ++ 14?decltype(expr)
etdecltype((expr))
sont déjà différents en C ++ 11, cela généralise ce comportement.auto
aurait tout aussi bien fait le travail, car le résultat est retourné par valeur de toute façon ... Ou ai-je manqué quelque chose?Citant des trucs d' ici :
decltype(auto)
est principalement utile pour déduire le type de retour des fonctions de transfert et des wrappers similaires , où vous voulez que le type «suive» exactement une expression que vous invoquez.Par exemple, étant donné les fonctions ci-dessous:
Cependant,
decltype(auto)
n'est pas destiné à être une fonctionnalité largement utilisée au-delà de cela.En particulier, bien que cela puisse être utilisé pour déclarer des variables locales , cela n'est probablement qu'un anti-modèle car la référence d'une variable locale ne doit pas dépendre de l'expression d'initialisation.
En outre, il est sensible à la façon dont vous écrivez l'instruction return.
Par exemple, les deux fonctions ci-dessous ont des types de retour différents:
string
, le second retournestring&
, qui est une référence à la variable localestr
.À partir de la proposition, vous pouvez voir d'autres utilisations prévues.
la source
auto
pour le retour?auto
retour), mais l'OP a demandé spécifiquement des utilisations dedecltype(auto)
.auto lookup_a_string() { ... }
? Est-ce toujours un type sans référence? Et doncauto lookup_a_string() ->decltype(auto) { ... }
est-il nécessaire de forcer pour permettre aux références d'être (dans certains cas) retournées?auto
est défini en terme de modèle de passage par valeur, donc oui, il ne peut pas être une référence. Please-waitauto
peut être n'importe quoi, y compris une référence, bien sûr.std::vector
. Dites que vous aveztemplate<typename T> struct S { auto & operator[](std::size_t i) { return v[i]; } std::vector<T> v; }
. PuisS<bool>::operator[]
retournera des références pendantes en raison de la spécialisation destd::vector<bool>
. Changer le type de retour pourdecltype(auto)
contourner ce problème.