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:
auto const& Example(int const& i)
{
return i;
}
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é:
template<class Fun, class... Args>
decltype(auto) Example(Fun fun, Args&&... args)
{
return fun(std::forward<Args>(args)...);
}
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 de decltype(auto)
.
template<int i>
struct Int {};
constexpr auto iter(Int<0>) -> Int<0>;
template<int i>
constexpr auto iter(Int<i>) -> decltype(auto)
{ return iter(Int<i-1>{}); }
int main() { decltype(iter(Int<10>{})) a; }
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 également
7.1.6.4 spéci fi cateur automatique [dcl.spec.auto]
1 Les spéci fi cateurs de type auto
et decltype(auto)
désignent un type d'espace réservé qui sera remplacé ultérieurement, soit par déduction d'un initialiseur, soit par spéci fi cation explicite avec un type de retour de fin. Le auto
spécificateur de type est également utilisé pour signifier qu'un lambda est un lambda générique.
2 Le type d'espace réservé peut apparaître avec un déclarateur de fonction dans le fichier decl-specifier-seq, type-specifier-seq, conversion-function-id ou trailing-return-type, dans tout contexte où un tel déclarateur est valide . Si le déclarateur de fonction inclut un type de retour de fin (8.3.5), qui spécifie le type de retour déclaré de la fonction. Si le type de retour déclaré de la fonction contient un type d'espace réservé, le type de retour de la fonction est déduit des instructions de retour dans le corps de la fonction, le cas échéant.
Le brouillon contient également cet exemple d'initialisation de variable:
int i;
int&& f();
auto x3a = i; // decltype(x3a) is int
decltype(auto) x3d = i; // decltype(x3d) is int
auto x4a = (i); // decltype(x4a) is int
decltype(auto) x4d = (i); // decltype(x4d) is int&
auto x5a = f(); // decltype(x5a) is int
decltype(auto) x5d = f(); // decltype(x5d) is int&&
auto x6a = { 1, 2 }; // decltype(x6a) is std::initializer_list<int>
decltype(auto) x6d = { 1, 2 }; // error, { 1, 2 } is not an expression
auto *x7a = &i; // decltype(x7a) is int*
decltype(auto)*x7d = &i; // error, declared type is not plain decltype(auto)