Ответ 1
GCC прямо на этом.
Выражения, безусловно, constant-expression
s *, поскольку они назначены переменной constexpr
. Однако до С++ 14 существуют дополнительные ограничения на то, что разрешено для аргумента шаблона указателя.
С++ 14 черновик N4140 [temp.arg.nontype]
1 Аргумент шаблона для непигового шаблона-шаблона без шаблона должен быть одним из:
- для нетипового шаблона-параметра интегрального или перечисляемого типа, преобразованное константное выражение (5.19) типа Шаблон-параметры; или
- имя несимметричного шаблона; или
- постоянное выражение (5.19), которое обозначает адрес полного объекта со статическим временем хранения и внешним или внутренним связь или функция с внешней или внутренней связью, включая шаблонов функций и шаблонов-шаблонов функций, но исключая нестатические члены класса, , выраженные (игнорируя круглые скобки), как
&id-expression
, где id-выражение - это имя объекта или кроме того, что и может быть опущено, если имя относится к функции или массива и должны быть опущены, если соответствующие шаблон-параметр является ссылкой; или- константное выражение, которое вычисляет значение нулевого указателя (4.10); или постоянное выражение, которое вычисляет значение указателя нулевого элемента (4.11); или указатель на элемент, выраженный как описано в 5.3.1; или константное выражение типа std:: nullptr_t.
Для foo<dum_ptr>()
, dum_ptr
не выражается как &name
, а для foo<&dum_ref>()
, dum_ref
не является именем объекта, это имя ссылки на объект, поэтому оба запрещены как аргументы шаблона.
Эти ограничения снимаются в С++ 17, чтобы разрешить любой constexpr, поэтому поэтому он работает там:
С++ 17 черновик N4606 - 14.3.2 Шаблон непиговых аргументов [temp.arg.nontype]
1 Аргумент шаблона для параметра шаблона, не относящегося к типу, должен быть преобразованное постоянное выражение (5.20) типа Шаблон-параметры. Для шаблона-шаблона, не относящегося к типу ссылки или тип указателя, значение константного выражения не должно ссылаться на (или для типа указателя, не должен быть адресом):
- (1.1) подобъект (1.8),
- (1.2) временный объект (12.2),
- (1.3) строковый литерал (2.13.5),
- (1.4) результат выражения типа (5.2.8) или
- (1.5) предопределенная переменная __func__ (8.4.1).
Как обычно, clang дает лучшие сообщения об ошибках: https://godbolt.org/g/j0Q2bV
* (см. выражение константы адреса и ссылочное константное выражение)