std::bit_cast 生成多个值的值表示的示例是什么?
What would be an example where std::bit_cast produces a value representation of multiple values?
以下是 [bit.cast] 下的标准(草案 n4861)的引用(强调是我的)
Returns: An object of type To
. Implicitly creates objects nested within the result (6.7.2). Each bit of the value representation of the result is equal to the corresponding bit in the object representation of from
. Padding bits of the result are unspecified. For the result and each object created within it, if there is no value of the object’s type corresponding to the value representation produced, the behavior is undefined. If there are multiple such values, which value is produced is unspecified.
所以我的问题是,std::bit_cast
产生对应于多个不同值的值表示的场景示例是什么?
想到求和类型。联合可以有相同类型的成员:
union u {
int a;
int b;
};
现在,如果我们 bit-cast 一些东西变成 u
,我们会得到什么样的 u
?是 a
处于活动状态还是 b
?这些是 u
的形式不同的值,但它们似乎具有相同的值表示形式。
在原来的提案中,那段写成:http://wg21.link/P0476r1
Returns: an object of type To
whose object representation is equal to the object representation of From
. If multiple object representations could represent the value representation of From
, then it is unspecified which To
value is returned. If no value representation corresponds to To
's object representation then the returned value is unspecified.
所以它的意图似乎是允许更改填充位。也就是说,对于 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);
填充字节允许不同(因此多个 bit_cast
允许 return 不同的值,但 round-trip 位转换将在这种情况下保存值)
但似乎有些情况会破坏 round-tripping。考虑这种情况 (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
允许第一个断言通过(在未优化的构建中也是如此)。当它通过时,第二个通常也会通过。当bit_cast
变回int*
时,什么索引应该有效? [-1]
得到b[0]
的值(如果是std::end(b)
),或者0
得到a[0]
的值(如果是std::begin(a)
)?好像不详
在其他情况下,指针可以具有相同但不同的值。对于数组 T[N]
,将其地址 T(*)[N]
转换为 void*
与将指向第一个元素的指针 T*
转换为 [=31] 具有相同的值=].将空 class 成员与 [[no_unique_address]]
.
一起使用时也会发生同样的情况
以下是 [bit.cast] 下的标准(草案 n4861)的引用(强调是我的)
Returns: An object of type
To
. Implicitly creates objects nested within the result (6.7.2). Each bit of the value representation of the result is equal to the corresponding bit in the object representation offrom
. Padding bits of the result are unspecified. For the result and each object created within it, if there is no value of the object’s type corresponding to the value representation produced, the behavior is undefined. If there are multiple such values, which value is produced is unspecified.
所以我的问题是,std::bit_cast
产生对应于多个不同值的值表示的场景示例是什么?
想到求和类型。联合可以有相同类型的成员:
union u {
int a;
int b;
};
现在,如果我们 bit-cast 一些东西变成 u
,我们会得到什么样的 u
?是 a
处于活动状态还是 b
?这些是 u
的形式不同的值,但它们似乎具有相同的值表示形式。
在原来的提案中,那段写成:http://wg21.link/P0476r1
Returns: an object of type
To
whose object representation is equal to the object representation ofFrom
. If multiple object representations could represent the value representation ofFrom
, then it is unspecified whichTo
value is returned. If no value representation corresponds toTo
's object representation then the returned value is unspecified.
所以它的意图似乎是允许更改填充位。也就是说,对于 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);
填充字节允许不同(因此多个 bit_cast
允许 return 不同的值,但 round-trip 位转换将在这种情况下保存值)
但似乎有些情况会破坏 round-tripping。考虑这种情况 (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
允许第一个断言通过(在未优化的构建中也是如此)。当它通过时,第二个通常也会通过。当bit_cast
变回int*
时,什么索引应该有效? [-1]
得到b[0]
的值(如果是std::end(b)
),或者0
得到a[0]
的值(如果是std::begin(a)
)?好像不详
在其他情况下,指针可以具有相同但不同的值。对于数组 T[N]
,将其地址 T(*)[N]
转换为 void*
与将指向第一个元素的指针 T*
转换为 [=31] 具有相同的值=].将空 class 成员与 [[no_unique_address]]
.