不要问我为什么,但我试图在编译时初始化一个指针数组(指针指向另一个静态数组的元素)。这涉及 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:
A template-argument for a non-type, non-template template-parameter shall be one of:
- ...
- a constant expression (5.19) that designates the address of an object with static storage duration and external or internal linkage or a function with external or internal linkage, including function templates and function template-ids but excluding non-static class members, expressed (ignoring parentheses) as
&
id-expression, except that the&
may be omitted if the name refers to a function or array and shall be omitted if the corresponding template-parameter is a reference; or- ...
(强调我的,省略了不适用于此的其他要点)。
为了完整起见,id-expression 在 5.1.1 中定义为限定或非限定标识符、运算符名称、析构函数名称或模板标识符。那里不允许 []
。
关于C++11:模板中的(递归)指针算术 (TMP),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26582944/