遇到的具体问题是编译器如何处理它有一些不一致。
例如这段代码(https://godbolt.org/z/08Z-zi):
constexpr auto value = 1;
static_assert(*const_cast<int *>(&value), "value should be 1");
使用GCC,Clang和MSVC编译良好,但在英特尔C ++编译器19.0.1中失败,并出现以下错误:
error: expression must have a constant value
static_assert(*const_cast<int *>(&value), "value should be 1");
据我所知,标准没有明确说明在常量表达式中不允许使用const_cast
。通过结果指针写入将是未定义的,因此不允许,但读取应该没问题。
考虑到所有主要编译器都编译此代码(包括ICC <19.0.1),它可能只是ICC 19.0.1中的回归。
C ++中常量表达式中可能出现或未出现的内容由表达式的黑名单或表达式属性定义。完整列表位于[expr.const]部分,第2段。列表中没有任何内容禁止const_cast
本身。就我所见,唯一相关的是§2.7
除非适用,否则左值转换为左值
- 一个非整数或枚举类型的非易失性glvalue,它引用一个完整的非易失性const对象,具有前面的初始化,用常量表达式初始化,或者
- 一个非易失性glvalue,引用字符串文字的子对象,或
- 非易失性glvalue,引用constexpr定义的非易失性对象,或引用此类对象的不可变子对象,或者
- 文字类型的非易失性glvalue,指的是一个非易失性对象,其生命周期始于
e
的评估范围内;
对于(大致)“读取对象的存储值”,左值到右值的转换是标准的。这就是你的例子所做的。现在,这些可能不会出现在常数表达式中。除了前面的一个子弹适用之外。
第三个子弹适用于您的情况。 *
运算符产生左值。所述左值不易挥发,并且指的是constexpr
物体(value
)。因此,您的代码是有效的C ++。