constexpr 可以和 volatile 结合使用吗?
Can constexpr be combined with volatile?
以下代码片段在 Clang 3.5 中运行良好,但在 GCC 4.9.2 中运行不正常:
int main()
{
constexpr volatile int i = 5;
}
错误:
error: both 'volatile' and 'constexpr' cannot be used here
如果我检查 Clang 生成的程序集,它按预期显示 5
:
movl , -4(%rsp)
在 GCC 中,constexpr int i = 5
被优化掉了,但是 volatile int i = 5
也在汇编中显示了 5
。 volatile const int i = 5
在两个编译器中编译。一个东西同时是 volatile 和 const 并不是一个陌生的概念。
哪个编译器符合标准?
引用 N4140 [dcl.constexpr]/9:
A constexpr
specifier used in an object declaration declares the object as const
. Such an object shall have literal type and shall be initialized.
文字类型定义在[basic.types]/10:
A type is a literal type if it is:
(10.1) — void
; or
(10.2) — a scalar type; or
(10.3) — a reference type; or
(10.4) — an array of literal type; or
(10.5) — a class type (Clause 9) that has all of the following properties:
(10.5.1) — it has a trivial destructor,
(10.5.2) — it is an aggregate type (8.5.1) or has at least one constexpr
constructor or constructor template that is not a copy or move constructor, and
(10.5.3) — all of its non-static data members and base classes are of non-volatile literal types.
标量类型在第 9 段中:
Arithmetic types (3.9.1), enumeration types, pointer types, pointer to member types (3.9.2), std::nullptr_t
, and cv-qualified versions of these types (3.9.3) are collectively called scalar types.
int
是算术,所以 volatile int
是标量类型,因此是文字类型。 constexpr volatile int i = 5;
因此是一个格式正确的声明。
有趣的是,计算 i
的表达式不能是 core-constant-expression,因为它将左值到右值转换应用于 volatile 类型的左值([expr.const]/2)。因此,计算 i
的表达式既不是 整数常量表达式 也不是 常量表达式 。我不确定该声明中的 constexpr
除了使 i
隐式 const
和(向 点头)要求其初始值设定项为常量表达式之外还有什么影响.
我已将此报告为 GCC bug 65327,我们将看看 GCC 的人怎么说。
2015-03-16 更新:修复了 GCC 5 的错误。
是的,这是有效的,为此提交了 defect report 1688: Volatile constexpr variables ,说:
There does not appear to be language in the current wording stating
that constexpr cannot be applied to a variable of volatile-qualified
type. Also, the wording in 5.19 [expr.const] paragraph 2 referring to
“a non-volatile object defined with constexpr” might lead one to infer
that the combination is permitted but that such a variable cannot
appear in a constant expression. What is the intent?
它被拒绝为不是缺陷(NAD),响应和理由是:
The combination is intentionally permitted and could be used in some
circumstances to force constant initialization.
正如 DR 指出的那样,这样的变量本身不能用于 常量表达式:
constexpr volatile int i = 5;
constexpr int y = i ; // Not valid since i is volatile
第 [expr.const]/2 部分包括使条件表达式不是核心常量表达式的所有情况,包括:
an lvalue-to-rvalue conversion (4.1) unless it is applied to
所有例外要求:
[...]that refers to a non-volatile [...] object [...]
以下代码片段在 Clang 3.5 中运行良好,但在 GCC 4.9.2 中运行不正常:
int main()
{
constexpr volatile int i = 5;
}
错误:
error: both 'volatile' and 'constexpr' cannot be used here
如果我检查 Clang 生成的程序集,它按预期显示 5
:
movl , -4(%rsp)
在 GCC 中,constexpr int i = 5
被优化掉了,但是 volatile int i = 5
也在汇编中显示了 5
。 volatile const int i = 5
在两个编译器中编译。一个东西同时是 volatile 和 const 并不是一个陌生的概念。
哪个编译器符合标准?
引用 N4140 [dcl.constexpr]/9:
A
constexpr
specifier used in an object declaration declares the object asconst
. Such an object shall have literal type and shall be initialized.
文字类型定义在[basic.types]/10:
A type is a literal type if it is:
(10.1) —
void
; or(10.2) — a scalar type; or
(10.3) — a reference type; or
(10.4) — an array of literal type; or
(10.5) — a class type (Clause 9) that has all of the following properties:
(10.5.1) — it has a trivial destructor,
(10.5.2) — it is an aggregate type (8.5.1) or has at least one
constexpr
constructor or constructor template that is not a copy or move constructor, and(10.5.3) — all of its non-static data members and base classes are of non-volatile literal types.
标量类型在第 9 段中:
Arithmetic types (3.9.1), enumeration types, pointer types, pointer to member types (3.9.2),
std::nullptr_t
, and cv-qualified versions of these types (3.9.3) are collectively called scalar types.
int
是算术,所以 volatile int
是标量类型,因此是文字类型。 constexpr volatile int i = 5;
因此是一个格式正确的声明。
有趣的是,计算 i
的表达式不能是 core-constant-expression,因为它将左值到右值转换应用于 volatile 类型的左值([expr.const]/2)。因此,计算 i
的表达式既不是 整数常量表达式 也不是 常量表达式 。我不确定该声明中的 constexpr
除了使 i
隐式 const
和(向
我已将此报告为 GCC bug 65327,我们将看看 GCC 的人怎么说。
2015-03-16 更新:修复了 GCC 5 的错误。
是的,这是有效的,为此提交了 defect report 1688: Volatile constexpr variables ,说:
There does not appear to be language in the current wording stating that constexpr cannot be applied to a variable of volatile-qualified type. Also, the wording in 5.19 [expr.const] paragraph 2 referring to “a non-volatile object defined with constexpr” might lead one to infer that the combination is permitted but that such a variable cannot appear in a constant expression. What is the intent?
它被拒绝为不是缺陷(NAD),响应和理由是:
The combination is intentionally permitted and could be used in some circumstances to force constant initialization.
正如 DR 指出的那样,这样的变量本身不能用于 常量表达式:
constexpr volatile int i = 5;
constexpr int y = i ; // Not valid since i is volatile
第 [expr.const]/2 部分包括使条件表达式不是核心常量表达式的所有情况,包括:
an lvalue-to-rvalue conversion (4.1) unless it is applied to
所有例外要求:
[...]that refers to a non-volatile [...] object [...]