Restituisce l'inoltro del tipo in codice generico
Per il codice non generico, come nell'esempio iniziale che hai fornito, puoi selezionare manualmente per ottenere un riferimento come tipo di ritorno:
auto const& Example(int const& i)
{
return i;
}
ma nel codice generico vuoi essere in grado di inoltrare perfettamente un tipo restituito senza sapere se hai a che fare con un riferimento o un valore. decltype(auto)
ti dà quell'abilità:
template<class Fun, class... Args>
decltype(auto) Example(Fun fun, Args&&... args)
{
return fun(std::forward<Args>(args)...);
}
Ritardare la detrazione del tipo restituito nei modelli ricorsivi
In queste domande e risposte, alcuni giorni fa, si è verificata una ricorsione infinita durante l'istanza del modello quando il tipo di ritorno del modello è stato specificato come decltype(iter(Int<i-1>{}))
anziché 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)
viene utilizzato qui per ritardare la detrazione del tipo restituito dopo che si è risolta la polvere dell'istanza del modello.
Altri usi
È inoltre possibile utilizzare decltype(auto)
in altri contesti, ad esempio la bozza della norma N3936 afferma anche
7.1.6.4 speci fi catore automatico [dcl.spec.auto]
1 I parametri auto
e decltype(auto)
type designano un tipo di segnaposto che verrà sostituito in seguito, deducendo da un inizializzatore o specificando esplicitamente un tipo-trailing-return. Lo auto
speci fi catore di tipo viene utilizzato anche per indicare che un lambda è un lambda generico.
2 Il tipo di segnaposto può apparire con un dichiaratore di funzione in decl-specificatore-seq, tipo-specificatore-seq, conversione-funzione-id o tipo-trailing-return, in qualsiasi contesto in cui tale dichiaratore è valido . Se il dichiaratore di funzione include un tipo di ritorno finale (8.3.5), che specifica il tipo di ritorno dichiarato della funzione. Se il tipo di ritorno dichiarato della funzione contiene un tipo di segnaposto, il tipo di ritorno della funzione viene dedotto dalle dichiarazioni di ritorno nel corpo della funzione, se presenti.
La bozza contiene anche questo esempio di inizializzazione variabile:
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)