当前的草案标准(以及预计的C++17)在[basic.compound/4]中提到:
[注意:数组对象及其第一个元素虽然具有相同的地址,但它们不能互相转换为指针。— 结束注意事项 —]
因此,一个对象的指针不能通过reinterpret_cast
转换为其所在的数组指针。
现在,有了std::launder
,[ptr.launder/1]:
template<class T> [[nodiscard]] constexpr T* launder(T* p) noexcept
;要求:
p
表示内存中一个字节的地址A。一个类型与T相似且在其生命周期内的对象X位于地址A处。通过结果可以访问到的所有存储字节也可以通过p
访问到(见下文)。
而可访问的定义在[ptr.launder/3]中:
备注:只要其参数的值可以在核心常量表达式中使用,就可以在核心常量表达式中使用此函数的调用。如果通过指向对象Y的指针值可以访问存储器中的一个字节,那么该字节就是通过指向Y的指针值、与Y可互相转换的对象或者如果Y是数组元素,则是立即封闭的数组对象而可访问的。如果T是函数类型或cv void,则程序是非法的。
现在,乍一看,似乎std::launder
可以用来进行上述转换,因为我强调了其中的一部分。
但是。如果p
指向一个数组对象,根据这个定义,数组的字节是可访问的(即使p
与数组指针不可互相转换),就像launder的结果一样。因此,这个定义似乎对这个问题没有任何说明。
std::launder
可以用来将对象指针转换为其所属数组指针吗?
p + 1
。您可以从任何一个元素到达任何其他元素。然而,指针互换性是指转换为指向整个数组的指针,例如int (*) [10]
,这是完全不同的故事。您不需要这种可互换性即可访问其他元素。 - AnT stands with Russia