Kae*_*Rin 4 c++ language-lawyer c++20
以下是引用自[bit.cast]下的标准(草案n4861)(强调的是我的)
返回:类型的对象
To。隐式创建嵌套在结果中的对象 (6.7.2)。结果的值表示的每一位都等于 的对象表示中的相应位from。结果的填充位未指定。对于结果和其中创建的每个对象,如果没有与所产生的值表示对应的对象类型的值,则行为是未定义的。如果有多个这样的值,生成哪个值是未指定的。
所以我的问题是,std::bit_cast生成对应于多个不同值的值表示的场景的示例是什么?
总和类型浮现在脑海中。联合可以有相同类型的成员:
union u {
int a;
int b;
};
Run Code Online (Sandbox Code Playgroud)
现在,如果我们将一些东西位投射到 a 中u,u我们会得到什么样的结果?它是一个a活跃的地方还是一个b?这些是 a 形式上不同的值u,但它们似乎具有相同的值表示。
在最初的提案中,该段落写为:http://wg21.link/P0476r1
返回: 类型的对象
To,其对象表示形式等于 的对象表示形式From。如果多个对象表示可以表示的值表示From,则未指定To返回哪个值。如果没有值表示对应于To的对象表示,则返回值未指定。
所以看起来意图是允许改变填充位。也就是说,具有From不同填充的相同值表示有多种可能的对象表示,因此具有To不同值的多种可能值表示。例如,当bit_cast像这样:
struct foo {
std::uint8_t a;
// 1 byte padding to align
std::uint16_t b;
};
bit_cast<std::uint32_t>(foo_value);
Run Code Online (Sandbox Code Playgroud)
填充字节允许不同(因此bit_cast允许多个 s 返回不同的值,但在这种情况下,往返位转换将保存值)
但似乎有些情况会破坏往返。考虑这种情况(https://godbolt.org/z/KGTGes):
int a[1];
int b[1];
assert(std::begin(a) == std::end(b)); // 1
std::uintptr_t a_bits = std::bit_cast<std::uintptr_t>(std::begin(a));
std::uintptr_t b_bits = std::bit_cast<std::uintptr_t>(std::end(b));
assert(a_bits == b_bits); // 2
Run Code Online (Sandbox Code Playgroud)
第一个断言被允许通过(并且在未优化的构建中也是如此)。当它确实过去时,第二个通常也会过去。当bit_cast回到 时int*,什么索引应该有效?[-1]获取b[0](如果是std::end(b)) 的值,或者0(a[0]如果是std::begin(a)) 的值?好像没有具体说明
在其他情况下,指针可以具有相同的值但不同。对于 array T[N],将其地址 a 转换为 与T(*)[N]将指针转换为void*第一个元素 a 具有相同的值。将空类成员与 一起使用时也会发生同样的情况。T*void*[[no_unique_address]]
| 归档时间: |
|
| 查看次数: |
147 次 |
| 最近记录: |