Подтвердить что ты не робот

Ссылка рушится?

Пытаясь решить эту проблему, мне стало интересно. Рассмотрим следующий код:

template <typename T>
struct foo 
{
    foo(T const& x) : data(x) {}
    T data;
};

Кажется, что я могу построить объект типа foo<T const&> без ошибок, гипотетический T const& const& понимается как T const&.

Похоже, что это называется сбрасыванием ссылок, но я никогда не слышал этого термина раньше (см. комментарии в связанном вопросе).

Это широко распространено? Является ли этот стандарт?

4b9b3361

Ответ 1

В С++ 03 было не законно делать следующие

typedef int &ref;
ref &r = ...; // reference to reference!

Это часто вызывает проблемы для компиляции людей с действительно строгими или старыми компиляторами С++ 03 (GCC4.1, а также Comeau 8/4/03 не нравятся выше), потому что привязки объектов стандартных функций не заботятся "ссылка на ссылку", а иногда и создавать такие нелегальные типы.

В С++ 0x это называется "сбрасыванием ссылок", да. Большинство современных компиляторов С++ 03 делают это (например, T&, где T обозначает ссылочный тип T снова), путем ретроактивного применения правила. Библиотека boost.call_traits позволяет легко объявлять такие параметры функции, так что ситуация "ссылка на ссылку" не возникает.

Обратите внимание, что const не действует. A const, примененный к эталонному типу, игнорируется. Поэтому, даже если компилятор поддерживает свертывание ссылок, следующее не является законным.

int const x = 0;

// illegal: trying to bind "int&" to "int const"!
ref const& r = x; 

Ответ 2

Согласно this, на С++ 98 была только ограниченная поддержка ссылочного коллапса:

В С++ 98 имеется только одна ссылка правило сбрасывания: T & и или ссылку к ссылке, сворачивается в T &:

void g(int & ri) {++ri;} // int& & -> int& 
void f(int & ri) {g(ri);}

Даже там, незаконно пытаться объявить переменную, которая является ссылкой на ссылку:

int ben;
int& bill(ben);     // OK
int & & bob(bill);  // error C2529: 'bob' : reference to reference is illegal