C++ constexpr和const的混合使用?

C++ constexpr和const的混合使用?,c++,c++11,constants,clang,C++,C++11,Constants,Clang,我读了一点关于标准库的CLang实现,它让我对const和constexpr有点困惑 template<class _Tp, _Tp __v> struct integral_constant { static constexpr _Tp value = __v; }; template<class _Tp, _Tp __v> const _Tp integral_constant<_Tp, __v>::value; 而constexpr应该解决这

我读了一点关于标准库的CLang实现,它让我对const和constexpr有点困惑

template<class _Tp, _Tp __v>
struct integral_constant
{
    static constexpr _Tp value = __v;
};

template<class _Tp, _Tp __v>
const _Tp integral_constant<_Tp, __v>::value;
而constexpr应该解决这个问题,所以至少在这种情况下,constexpr是不允许的,如下所示

struct S {
    static const int size;
};
constexpr int limit = 2 * S::size; // shall be error in my understanding
const int S::size = 256;

然而,在阅读C++标准草案N32 25之后,我没有明确指出上述示例会导致错误。特别是从7.1.5/9开始

应用程序中使用的constexpr说明符 对象声明声明对象 作为常量。这种物体应具有 应初始化文本类型和。 如果它是由构造函数初始化的 调用时,构造函数应为 constexpr构造函数和每个 构造函数的参数应为 恒定表达式。那个电话应该 是一个常量表达式(5.19)。 否则,每一个完整的表达 在其初始值设定项中出现的应为 恒定表达式

因此,如果constexpr int limit=2*S::size;是无效的,那么S::size不能是常量表达式,那么从5.19(常量表达式)开始,我看不到标准不允许上面示例中的2*S::size不是常量表达式

有人能指出我忽略了什么吗?非常感谢。

“在初始值设定项中出现的每个完整表达式都应该是一个常量表达式”


S::size
不是常量表达式,因此它不能出现在常量表达式的初始化中。

S::size不是N3225§5.19p2规定的常量表达式:

条件表达式是一个常量表达式,除非它涉及以下内容之一

  • 左值到右值的转换(4.1),除非应用于
    • 整型或枚举类型的glvalue,它引用具有先前初始化、使用常量表达式初始化或
    • [其他不适用的条件]
请注意,我引用的第二个要点如何允许使用常量表达式初始化的整型静态数据成员也是常量表达式,但您的S::size未初始化

(边注:常数表达式是以条件表达式定义的,因为C++语法是这样工作的) 如果您想知道左值到右值的转换是如何发生的,请参见§5p9:

每当glvalue表达式作为期望该操作数具有prvalue的运算符的操作数出现时,将应用左值到右值(4.1)、数组到指针(4.2)或函数到指针(4.3)的标准转换将表达式转换为prvalue


这可能是如何阅读标准的一个很好的例子,尽管对于0x还没有太多其他可用的方法。

我的问题实际上是:为什么s::size不是一个常量表达式?我读了5.19(常量表达式)好几遍,没有发现它提到S::size不是常量表达式的情况。嗨,谢谢。我忽略了它。然而,尽管我确实发现很多人在互联网上这样说,但我仍然没有找到提到的标准中的哪一个:赋值运算符期望右边为右值,二进制算术运算符期望两个操作数都为右值。这绝对是正确的规则,但问题不在于
S::size
没有用常量表达式初始化,因为它的定义确实有这样的初始化。问题在于顺序:规则需要预先初始化,这里的定义和初始化遵循尝试的用法。
struct S {
    static const int size;
};
constexpr int limit = 2 * S::size; // shall be error in my understanding
const int S::size = 256;