为什么在类中初始化的非整数静态数据成员必须是constexpr?

时间:2013-10-24 19:49:57

标签: c++ c++11 static-members constexpr

在类定义中初始化的静态整数数据成员可以声明为constconstexpr,但在类定义中初始化的非整数静态数据成员必须是constexpr

class MyClass {
  static const     int   w = 5;          // okay
  static constexpr int   x = 5;          // okay
  static const     float y = 1.5;        // error!
  static constexpr float z = 1.5;        // okay
};

有人知道为什么不允许y的声明吗?标准的非法部分是9.4.2 / 3,但为什么是非法的?

3 个答案:

答案 0 :(得分:4)

在C ++ 11之前,您无法在类声明中初始化非整数/枚举类型的静态成员(但您可以在类声明之外)。管理constexpr的规则会带来前进,但允许您在课程声明中使用constexpr对其进行初始化(因此您不再需要以下代码):

struct A
{
    static const float pi;
};

const float A::pi = 3.1415;

此规则的一个副作用是简化您的类结构而不是让它变得丑陋(如上面的代码)。

在C ++ 11添加constexpr之前的情况之一的原因之一是标准没有指定如何实现浮点(它留给处理器/体系结构 - 例如,当您说float x = 1.6f时,在大多数系统上它实际上是1.6000000000024

答案 1 :(得分:2)

float有点难以描述动机,但想象一下班级成员:

class MySpecialInt {
public:
    constexpr MySpecialInt(const int & other) {
    }
};
class MyClass {
    static const     MySpecialInt a = 5; // error
    static constexpr MySpecialInt b = 5; // okay
};

a在这种情况下可能有一些非平凡的结构,可能违反(或至少非常复杂)单定义规则。由于constexpr保证了限制性编译时属性,b的复制构造函数必须也是constexpr,因此保证返回定义良好的编译时的值(和 NOT 违反单一定义规则)

为什么float表现出这种行为我认为只是出于遗留原因,因为float传统上从未像这样初始化("因为标准是这样说的"),所以他们在static的保护下抓住了初始化const float constexpr个成员。

答案 2 :(得分:0)

可能是因为非整数i也可能包含像char这样的数据类型,这就是为什么你不能使它们保持不变并需要常量表达的原因。但是在积分的情况下,你可以使它们成为常量表达式或不变。因此,因为char只能是一个常量表达式,所以对于所有非整数值都是非法的。