Ответ 1
Введение
Верно сказать, что имя ссылки - это id-выражение; id-выражение не ссылается на ссылку, на которую ссылается ссылка, но сама ссылка.
int a = 0;
int& ref = a; // "ref" is an id-expression, referring to `ref` - not `a`
Стандарт (N4140)
Вы цитируете соответствующие разделы стандарта в своем сообщении, но вы не указали наиболее важную часть (подчеркните мою):
14.3.2p1 Шаблоны без аргументов [temp.arg.nontype]
Аргумент шаблона для непигового шаблона-шаблона без шаблона должен быть одним из следующих:
<суб > ...суб >
постоянное выражение (5.19), которое обозначает адрес полного объекта со статической продолжительностью стеллажа и внешней или внутренней связью или функцией с внешней или внутренней связью, включая функциональные шаблоны и функцию template-ids, но исключая нестатические члены класса, выраженные (игнорируя круглые скобки) как
&
id-expression, , где id-выражение - это имя объекта или функции, за исключением того, что&
может быть опущено, если имя относится к функции или массиву и должно быть опущено, если соответствующий шаблон-параметр является ссылкой; <Суб > ...суб >
Примечание: В более ранних черновиках "где id-выражение - это имя объекта или функции" отсутствует; он был рассмотрен DR 1570 - это, несомненно, делает намерение более ясным.
Переменная ссылочного типа не является объектом?
Вы абсолютно правы; сама ссылка имеет ссылочный тип и может просто действовать как объект, когда часть выражения.
5p5 Выражения [expr]
Если выражение первоначально имеет тип "ссылка на
T
" (8.3.2, 8.5.3), тип доводится доT
до любого дальнейшего анализа. Выражение обозначает объект или функцию, обозначенные ссылкой, а выражение представляет собой значение lvalue или значение x, в зависимости от выражения.
Разработка
Очень важно отметить, что константное выражение ( "которое обозначает адрес полного объекта..." ) должно быть одним из &id-expression
или id-expression
.
Несмотря на то, что константное выражение, а не просто выражение id, может ссылаться на объект со статической продолжительностью хранения, мы не можем использовать его для "инициализации" шаблона-параметра ссылочного или указательного типа.
Пример фрагмента
template<int&>
struct A { };
int a = 0;
constexpr int& b = (0, a); // ok, constant-expression
A<(0, a)> c = {}; // ill-formed, `(0, a)` is not an id-expression
Примечание. Это также является причиной того, что мы не можем использовать строковые литералы как шаблонные аргументы; они не являются id-выражениями.