摒弃 constness - 标准中的数组和指针类型歧义

Casting away constness - array and pointer types ambiguity in the standard

下面您可以看到 reinterpret_cast 的三种不同变体,它们没有能力抛弃常量。 “抛弃常量”的定义在this section of the standard, and it specifically details pointer types, not array types. According to the standards, for multilevel pointers we keep checking for qualifier downcasts until we hit a non-pointer type(which array is). Refer to the following, which is also available in godbolt.

int * const *__restrict (*const *__restrict a)[2] {}; // ptr -> ptr -> arr -> ptr -> ptr -> int
reinterpret_cast<const double *__restrict (*const *__restrict)[2]>(a); // ptr -> ptr -> arr -> ptr -> double
reinterpret_cast<double *__restrict (*const *__restrict)[2]>(a);

// Fine because we've reached an array type
volatile int* const (* * const x) [2] {}; // ptr -> ptr -> arr -> ptr -> int
reinterpret_cast<int * * const * * const>(x); // ptr -> ptr -> ptr -> ptr -> int

// Fine because we've reached an array type
volatile int* const * const * * const y {}; // ptr -> ptr -> arr -> ptr -> int
reinterpret_cast<int * * const (* * const)[2]>(y); // ptr -> ptr -> ptr -> ptr -> int

在后面两个通过的测试用例中,我们明确删除了超过 arr 类型级别的限定符,并且我们没有放弃 constness。在顶部,我认为检查“抛弃常量”应该在第 3 级(均为数组类型)停止。事实并非如此,它产生了一个错误。我是否误读了标准中的内容?似乎 GCC 和 Clang 对于 C++17 都有这种行为。

感谢 Language Lawyer 指出这一点,但因为 C++17 草案规定,如果两种类型相似,则可以使用 const_cast 显式转换它们。类似的类型是多级 pointer/array 类型的每一级都相同的类型,即在 i-th 级我们有四个之一:

“pointer to”, “pointer to member of class Ci of type”, “array of Ni”, or “array of unknown bound of”

在这种情况下,因为整个类型相似,所以在 C++17 中第一个示例失败。在后两种情况下,类型类似于 array of Ni vs. pointer to,因此考虑到“丢弃常量”,其余类型被截断。