为什么常量指针不能成为常量表达式?

Arm*_*yan 30 c++ pointers constant-expression c++11

以下程序编译:

template <const int * P>
class Test{};

extern const int var = 42; //extern needed to force external linkage

int main()
{
    Test<&var> test;
}
Run Code Online (Sandbox Code Playgroud)

然而,这个没有,这对我来说是一个惊喜:

template <const int * P>
class Test{};

extern const int var = 42; //extern needed to force external linkage
extern const int * const ptr = &var; //extern needed to force external linkage
int main()
{
    Test<ptr> test; //FAIL! Expected constant expression.
}
Run Code Online (Sandbox Code Playgroud)

替代示例:

int main()
{
   const int size = 42;
   int ok[*&size]; //OK

   const int * const pSize = &size;
   int fail[*pSize]; //FAIL
}
Run Code Online (Sandbox Code Playgroud)

我得出的结论是,无论指针是const还是用常量表达式初始化,指针都不能是常量表达式.

问题:

  1. 我的结论是真的吗?
  2. 如果是这样,为什么指针不能成为常量表达式?如果没有,为什么上述程序不编译?
  3. C++ 0x(C++ 11,如果你愿意的话)会改变什么吗?

感谢您的任何见解!

Joh*_*itb 12

这有点复杂.在C++ 03和C++ 11中,&var如果var是本地静态/类静态或命名空间范围变量,则是常量表达式.这称为地址常量表达式.使用该常量表达式初始化类静态或命名空间范围指针变量可以保证在任何代码运行之前完成(静态初始化阶段),因为它是一个常量表达式.

但是只有从C++ 11开始,存储地址的constexpr指针变量&var也可以用作地址常量表达式,并且只有从C++ 11开始,你才可以取消引用地址常量表达式(实际上,你可以取消引用更多 - 甚至本地数组元素地址,但让它保持ontopic)并且如果它引用在取消引用之前初始化的常量整数变量或constexpr变量,则再次得到一个常量表达式(取决于类型和值类别,常量表达式的种类)可能会有所不同).因此,以下是有效的C++ 11:

int const x = 42;
constexpr int const *px = &x;

// both the value of "px" and the value of "*px" are prvalue constant expressions
int array[*px];
int main() { return sizeof(array); }
Run Code Online (Sandbox Code Playgroud)

如果是这样,为什么指针不能成为常量表达式?如果没有,为什么上述程序不编译?

这是标准措辞中的已知限制 - 它目前仅允许其他模板参数作为参数,或者& object对于指针类型的模板参数.尽管编译器应该能够做得更多.