GCC 4.7.2 fa non compilare questo quando viene specificato il flag -std=c++98
. Infatti, in C++ 98 (così come in C++ 03) i riferimenti ai riferimenti non collassano.
Un tentativo di un'istanza f<int&>
, dove T = int&
, produce il seguente identificativo funzione (qui a passare intenzionalmente la posizione del tipo di argomento T
e const
specificatore, che è consentito perché const T&
è uguale T const&
):
void f(int& const& t) // ERROR: reference to reference is illegal
Quanto sopra non è legale in C++ 98, né in C++ 03. Coerentemente, questo è l'errore che si ottiene da GCC 4.7.2:
Compilation finished with errors:
source.cpp: In function 'int main()':
source.cpp:15:14: error: no matching function for call to 'f(int&)'
source.cpp:15:14: note: candidate is:
source.cpp:5:6: note: template<class T> void f(const T&)
source.cpp:5:6: note: template argument deduction/substitution failed:
source.cpp: In substitution of 'template<class T> void f(const T&) [with T = int&]':
source.cpp:15:14: required from here
source.cpp:5:6: error: forming reference to reference type 'int&'
Tuttavia, se si utilizza il flag -std=c++11
, il compilatore esegue riferimento collasso quando si crea un'istanza del modello: un riferimento lvalue ad un riferimento lvalue diventa un di riferimento lvalue:
void f(int& const& t) == void f(int& t)
Qui la qualificazione const
viene scartato, perché si applica al riferimento, e non l'oggetto di riferimento. Poiché i riferimenti non possono essere riassegnati, sono di natura const
, motivo per cui lo const
è considerato superfluo e rimosso. Vedi this Q&A on SO per una spiegazione.
Ciò produce un riferimento di lvalue a un riferimento di lvalue, che si risolve in un semplice riferimento di lvalue. Quindi, la firma sul lato destro è istanziata.
Quanto sopra è un candidato valido per risolvere la chiamata per f<int&>(a)
e, pertanto, viene compilato senza errori.
Non riesco a trovare quella citazione in C++ 98 o C++ 03. §14.3.1 è "Argomenti tipo di modello" e non ha alcuna sottosezione o paragrafo 4. –