【发布时间】:2019-01-04 06:27:24
【问题描述】:
当前的标准草案(大概是 C++17)在[basic.compound/4] 中说:
[ 注意:数组对象和它的第一个元素不是指针可互转换的,即使它们具有相同的地址。 — 尾注 ]
所以指向对象的指针不能reinterpret_cast'd 来获取其封闭的数组指针。
现在,有std::launder,[ptr.launder/1]:
template<class T> [[nodiscard]] constexpr T* launder(T* p) noexcept;要求:
p表示内存中一个字节的地址 A。一个在其生命周期内且类型与 T 相似的对象 X 位于地址 A。可通过结果访问的所有存储字节都可通过p访问(见下文)。
而reachable的定义在[ptr.launder/3]:
备注:只要其参数的值可用于核心常量表达式,则可在核心常量表达式中使用此函数的调用。一个字节的存储空间可以通过一个指针值来访问,如果它在 Y 占用的存储空间内,则指向一个对象 Y,一个与 Y 指针可互转换的对象,或者如果 Y 是一个 立即封闭的数组对象数组元素。如果 T 是函数类型或 cv void,则程序格式错误。
现在,乍一看,std::launder 似乎可以用来进行上述转换,因为我已经强调了部分。
但是。如果p 指向一个数组的对象,那么根据这个定义,数组的字节是可达的(即使p 不是指针互转换为数组指针),就像洗钱的结果。所以,这个定义似乎没有说明这个问题。
那么,std::launder 可以用来将对象指针转换为其封闭的数组指针吗?
【问题讨论】:
-
“可达”这里是一个术语。 “备注:”段落的后半部分只是“需要:”段落中术语“可达”的解释/定义。
-
在数组的情况下,“可达”指的是简单的指针算法,如
p + 1。您可以从任何其他元素到达任何元素。指针互转换是指转换为指针指向整个数组,如int (*) [10],这是一个完全不同的故事。您不需要这种相互转换来访问其他元素。 -
@AnT:感谢您的澄清!
标签: c++ language-lawyer c++17