Необъяснимое поведение функции, принимающей универсальную ссылку и возвращающую ссылку на константу

Я всегда думал, что следующая функция, которая принимает универсальную ссылку, должна возвращать константу-ссылку.

template <typename T>
const T& Const(T&& val)
{
    return val;
}

Однако следующий код успешно компилируется с VS C++ и gcc:

int x = 5;
Const(x) = 6;

Значение переменной x равно 6 после запуска. Таким образом, функция Const возвращает неконстантную ссылку.

Чтобы получить ошибку компилятора, функция Const должна быть изменена, чтобы принять стандартную ссылку l-value или объявить как возвращающую const std::remove_reference_t<T>&.

Это почему? Какое правило я пропустил? Заранее спасибо!

Ответ 1

универсальная ссылка

Нет, они называются "справочными ссылками". Термин "универсальная ссылка" устарел.


Это почему?

Когда вы вызываете Const(x), x является lvalue, поэтому T выводится как int&. Тогда ваш тип возврата будет:

  • const T & = T const &int & const &int &

int & const & является ссылкой на const ссылку на int которая является такой же, как int&. (В этом случае const применяется к int&, а не только к int, как T = int&).