C++11:模板 (TMP) 中的(递归)指针算法



不要问我为什么,但我试图在编译时初始化一个指针数组(指针指向另一个静态数组的元素(。这涉及TMP,因此在构建可变参数列表时涉及模板递归。我已将问题缩小到以下内容:

template <int const * const P>
struct Foo
{
    constexpr static int const * const bar = P;
};
constexpr int const array[5] = {0, 1, 2, 3, 4}; // global, so has linkage
int main()
{
    /* 1 */ cout << *Foo<array>::bar << 'n';
    /* 2 */ cout << *Foo<array + 1>::bar << 'n';
    /* 3 */ cout << *Foo<&array[1]>::bar << 'n';
}

案例 1 工作正常,并打印"0"。

案例 2 无法编译,GCC (4.9.1( 抱怨:

error: ‘(((const int*)(& array)) + 4u)’ is not a valid template argument for ‘const int*’ because it is not the address of a variable
 cout << *Foo<array + 1>::bar << 'n';
                       ^

案例 3 没有编译,GCC 抱怨:

error: template argument 1 is invalid
 cout << *Foo<&array[1]>::bar << 'n';

我主要关注的是案例2。为什么不能做常量指针算术并将结果传递给模板?

您说得对,在指定指针类型的非类型模板参数时,不可能进行任何指针算术。该标准明确指出,C++11 14.3.2/1:

类型、非模板模板参数的模板参数应为以下参数之一:

  • 一个常量表达式 (5.19(,它指定具有静态存储持续时间和 外部或内部链接或具有外部或内部链接的功能,包括功能模板 和函数模板 ID,但不包括非静态类成员,表示(忽略括号(为 & id 表达式,但如果名称引用函数或数组,则可以省略&,并且 如果相应的模板参数是引用,则省略;或

(强调我的,省略了这里不适用的其他要点(。

为了完整起见,id-expression 在 5.1.1 中定义为限定或非限定标识符、运算符名称、析构函数名称或模板标识符。 那里不允许[]

最新更新