指针作为非类型模板参数

时间:2013-04-08 17:36:22

标签: c++ templates

在回答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

2 个答案:

答案 0 :(得分:2)

考虑使用静态成员Foo<&X>的课程Foo<&Y>int Bar。链接器必须能够判断您的程序是否有1个或2个Bar个对象。现在考虑链接器也是最有可能负责将值分配给&X&Y的一方。

再次查看标准。在编写时,编译器不需要将实际的地址传递给链接器。相反,它传递id-expression。即使在为它们分配数字地址之前,链接器已经能够确定两个id-expression是否相同。

答案 1 :(得分:0)

  1. 它不能是变量,因为变量只在运行时设置。
  2. 它不能是constexpr,因为在编译时无法知道地址的;在大多数情况下,它只会在执行前重新定位后修复。
  3. 理论上它可能是一个算术表达式(即使它在标准中不允许),但在数组元素地址的常见情况下,您只需使用&arr[i]而不是{{1 }}。