Отвечая на этот вопрос SO, я нашел в стандарте (уже С++ 03, все еще в С++ 11), что вы можете использовать только адреса как non -type, если они имеют форму & id-expression
(плюс некоторые исключения).
Но я не мог ответить, почему это так.
14.3.2 Шаблон аргументов non-type [temp.arg.nontype]
Аргумент шаблона для непигового шаблона-шаблона без шаблона должен быть одним из следующих:
[...]
- константное выражение (5.19), которое обозначает адрес объекта со статическим хранением > длительность и внешнюю или внутреннюю связь или функцию с внешней или внутренней связью, включая шаблоны функций и шаблоны функций, ids, но исключая нестатические члены класса, выраженные (игнорирующие круглые скобки) как и id-expression, за исключением того, что и могут быть опущены, если имя ссылается на функцию или массив и должно быть опущено, если соответствующий шаблон-параметр является ссылкой; [...]
(n3485, акцент мой)
Пример:
using TFoobar = int (*)();
template < TFoobar tp > struct foo_struct{};
int foobar() { return 42; }
constexpr TFoobar pFoobar = &foobar;
foo_struct < &foobar > o0; // fine
foo_struct < pFoobar > o1; // ill-formed
Я предполагаю, что это имеет какое-то отношение к фазам перевода, а именно, компилятор мало знает о адресах. Но почему это не разрешено? Не следует ли компилятору использовать что-то похожее на макроподстановку, чтобы заменить pFoobar
на &foobar
?