フラグが指定されている場合、GCC 4.7.2 はこれをコンパイルしません-std=c++98
。実際、C++98 (および C++03) では、参照への参照は折りたたまれません。
f<int&>
whereをインスタンス化しようとするとT = int&
、次の関数シグネチャが生成されます (ここでは、引数の型T
とconst
指定子の位置を意図的に入れ替えてconst T&
いT const&
ます。
void f(int& const& t) // ERROR: reference to reference is illegal
上記は C++98 でも C++03 でも正しくありません。一貫して、これは 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&'
それにもかかわらず、フラグを使用すると-std=c++11
、コンパイラはテンプレートをインスタンス化するときに参照の折りたたみを実行します。左辺値参照への左辺値参照は左辺値参照になります。
void f(int& const& t) == void f(int& t)
ここでconst
修飾子は削除されます。これは、参照先のオブジェクトではなく参照に適用されるためです。参照は再割り当てできないためconst
、本質的に存在します。そのため、const
は不要であると見なされ、削除されます。説明については、 SO に関するこの Q&A を参照してください。
これにより、単純な左辺値参照に解決される左辺値参照への左辺値参照が生成されます。したがって、右側の署名がインスタンス化されます。
上記は、呼び出しを解決する実行可能な候補であるf<int&>(a)
ため、エラーなしでコンパイルされます。