在回答this SO question时,我在标准(已经是C ++ 03,仍在C ++ 11中)中发现,如果他们是“非C”类型,那么您只能使用地址作为非类型模板参数。表格& id-expression
(加上一些例外情况)。
但我无法回答为什么就是这种情况。
14.3.2模板非类型参数[temp.arg.nontype]
非类型非模板模板参数的模板参数应为以下之一:
[...]
- 一个常量表达式(5.19),用于指定具有静态存储的对象的地址>持续时间和外部或内部链接或具有外部或内部链接的函数,包括函数模板和函数模板-id,但不包括非静态类成员,表示(忽略括号)为& 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
?
答案 0 :(得分:2)
考虑使用静态成员Foo<&X>
的课程Foo<&Y>
和int Bar
。链接器必须能够判断您的程序是否有1个或2个Bar
个对象。现在考虑链接器也是最有可能负责将值分配给&X
和&Y
的一方。
再次查看标准。在编写时,编译器不需要将实际的地址传递给链接器。相反,它传递id-expression
。即使在为它们分配数字地址之前,链接器已经能够确定两个id-expression
是否相同。
答案 1 :(得分:0)
constexpr
,因为在编译时无法知道地址的值;在大多数情况下,它只会在执行前重新定位后修复。&arr[i]
而不是{{1 }}。