GCC 4.7.2 не компилирует это, если указан флаг -std=c++98
. На самом деле в C++98 (как и в C++03) ссылки на ссылки не свертываются.
Попытка создать экземпляр f<int&>
, где 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
, компилятор выполняет свертывание ссылок при создании экземпляра шаблона: ссылка lvalue на ссылку lvalue становится ссылкой lvalue:
void f(int& const& t) == void f(int& t)
Здесь квалификатор const
отбрасывается, поскольку он применяется к ссылке, а не к объекту, на который указывает ссылка. Так как ссылки нельзя переназначить, они по своей природе const
, поэтому const
считаются лишними и удаляются. См. эти вопросы и ответы по SO для объяснения.
Это дает ссылку lvalue на ссылку lvalue, которая разрешается в простую ссылку lvalue. Таким образом, создается экземпляр подписи с правой стороны.
Приведенное выше является подходящим кандидатом для разрешения вызова f<int&>(a)
и, следовательно, компилируется без ошибок.
person
Andy Prowl
schedule
07.02.2013