Ответ 1
Универсальная ссылка, такая как T&&
, может выводить T
как "тип объекта" или "ссылочный тип"
В вашем примере он может выводить T
как int
при передаче rvalue, поэтому параметр функции int&&
или он может выводить T
как int&
при передаче lvalue, и в этом случае параметр функции int&
(поскольку правила сбрасывания ссылок говорят, что std::add_rvalue_reference<int&>::type
- это просто int&
)
Если T
не выводится вызовом функции (как в примере X::baz
), то его невозможно вывести на int&
, поэтому ссылка не является универсальной ссылкой.
Таким образом, IMHO действительно не нуждается в новом синтаксисе, он прекрасно вписывается в вычет аргумента шаблона и правила обращения с кодами, с небольшой настройкой, которую параметр шаблона можно вывести как ссылочный тип (где в С++ 03 используется шаблон функции параметр типа T
или T&
всегда выводит T
как тип объекта.)
Эти семантики и этот синтаксис были предложены с самого начала, когда в качестве решения проблемы переадресации были предложены ссылки rvalue и настройка правил вывода аргументов, см. N1385. Использование этого синтаксиса для обеспечения идеальной пересылки было предложено параллельно с предложением ссылок rvalue для целей семантики перемещения: N1377 находилась в той же рассылке, что и N1385. Я не думаю, что альтернативный синтаксис никогда всерьез не предлагался.
ИМХО альтернативный синтаксис на самом деле будет более запутанным в любом случае. Если у вас был template<typename T> void bar(T&@)
как синтаксис универсальной ссылки, но та же семантика, что и у нас сегодня, то при вызове bar(i)
параметр шаблона T
может быть выведен как int&
или int
, а параметр функции будет иметь тип int&
или int&&
... ни один из которых не является "T&@
" (независимо от того, что этот тип.) Таким образом, у вас будет грамматика на языке для декларатора T&@
, который не является типом который может когда-либо существовать, потому что он на самом деле всегда ссылается на какой-то другой тип: int&
или int&&
.
По крайней мере, с синтаксисом, который у нас есть, тип T&&
является реальным типом, а правила сворачивания ссылок не являются специфичными для функциональных шаблонов с использованием универсальных ссылок, они полностью согласуются с остальной системой типа вне шаблонов:
struct A {} a;
typedef A& T;
T&& ref = a; // T&& == A&
Или эквивалентно:
struct A {} a;
typedef A& T;
std::add_rvalue_reference<T>::type ref = a; // type == A&
Если T
- ссылочный тип lvalue, T&&
тоже. Я не думаю, что нужен новый синтаксис, правила действительно не настолько сложны или запутываются.