double 类型的静态 class 成员的常量表达式初始值设定项
Constant expression initializer for static class member of type double
在 C++11 和 C++14 中,为什么在以下代码段中需要 constexpr
:
class Foo {
static constexpr double X = 0.75;
};
而这个会产生编译器错误:
class Foo {
static const double X = 0.75;
};
并且(更令人惊讶的是)这个编译没有错误?
class Foo {
static const double X;
};
const double Foo::X = 0.75;
在C++03中我们只允许为枚举类型的const整型静态成员变量提供一个in class初始化器,在C++11中我们可以在in中初始化一个字面量类型的静态成员class 使用 constexpr。此限制在 C++11 中保留用于 const 变量,主要是为了与 C++03 兼容。我们可以从 closed issue 1826: const floating-point in constant expressions 中看到:
A const integer initialized with a constant can be used in constant expressions, but a const floating point variable initialized with a constant cannot. This was intentional, to be compatible with C++03 while encouraging the consistent use of constexpr. Some people have found this distinction to be surprising, however.
CWG 最终关闭了这个请求,认为它不是缺陷 (NAD),基本上是说:
that programmers desiring floating point values to participate in constant expressions should use constexpr instead of const.
供参考 N1804
最接近 C++03 的标准草案在 9.4.2
[class.static.data] 部分公开提供说:
If a static data member is of const integral or const enumeration type, its declaration in the class definition can
specify a constant-initializer which shall be an integral constant expression (5.19). In that case, the member can appear
in integral constant expressions. The member shall still be defined in a namespace scope if it is used in the program and
the namespace scope definition shall not contain an initializer.
和 C++11 标准草案 9.4.2
[class.static.data] 说:
If a non-volatile const static data member is of integral or enumeration type, its declaration in the class
definition can specify a brace-or-equal-initializer in which every initializer-clause that is an assignment expression
is a constant expression (5.19). A static data member of literal type can be declared in the
class definition with the constexpr specifier; if so, its declaration shall specify a brace-or-equal-initializer
in which every initializer-clause that is an assignment-expression is a constant expression. [...]
这在 C++14 标准草案中几乎相同。
In-class static const "definitions" 其实就是声明。定义变量时,编译器会为该变量分配内存,但这里不是这种情况,即获取这些 static-const-in-class 的地址格式不正确,NDR。
这些东西应该写到代码中,但是对于浮点类型来说不太容易做到,因此是不允许的。
通过在 class 之外定义静态 const 变量,您向编译器发出信号,这是真正的定义 - 具有内存位置的真实实例。
在 C++11 和 C++14 中,为什么在以下代码段中需要 constexpr
:
class Foo {
static constexpr double X = 0.75;
};
而这个会产生编译器错误:
class Foo {
static const double X = 0.75;
};
并且(更令人惊讶的是)这个编译没有错误?
class Foo {
static const double X;
};
const double Foo::X = 0.75;
在C++03中我们只允许为枚举类型的const整型静态成员变量提供一个in class初始化器,在C++11中我们可以在in中初始化一个字面量类型的静态成员class 使用 constexpr。此限制在 C++11 中保留用于 const 变量,主要是为了与 C++03 兼容。我们可以从 closed issue 1826: const floating-point in constant expressions 中看到:
A const integer initialized with a constant can be used in constant expressions, but a const floating point variable initialized with a constant cannot. This was intentional, to be compatible with C++03 while encouraging the consistent use of constexpr. Some people have found this distinction to be surprising, however.
CWG 最终关闭了这个请求,认为它不是缺陷 (NAD),基本上是说:
that programmers desiring floating point values to participate in constant expressions should use constexpr instead of const.
供参考 N1804
最接近 C++03 的标准草案在 9.4.2
[class.static.data] 部分公开提供说:
If a static data member is of const integral or const enumeration type, its declaration in the class definition can specify a constant-initializer which shall be an integral constant expression (5.19). In that case, the member can appear in integral constant expressions. The member shall still be defined in a namespace scope if it is used in the program and the namespace scope definition shall not contain an initializer.
和 C++11 标准草案 9.4.2
[class.static.data] 说:
If a non-volatile const static data member is of integral or enumeration type, its declaration in the class definition can specify a brace-or-equal-initializer in which every initializer-clause that is an assignment expression is a constant expression (5.19). A static data member of literal type can be declared in the class definition with the constexpr specifier; if so, its declaration shall specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression. [...]
这在 C++14 标准草案中几乎相同。
In-class static const "definitions" 其实就是声明。定义变量时,编译器会为该变量分配内存,但这里不是这种情况,即获取这些 static-const-in-class 的地址格式不正确,NDR。
这些东西应该写到代码中,但是对于浮点类型来说不太容易做到,因此是不允许的。
通过在 class 之外定义静态 const 变量,您向编译器发出信号,这是真正的定义 - 具有内存位置的真实实例。