(如何)我可以在具有一个成员的聚合类型和该成员的类型之间进行转换?
(How) can I cast between an aggregate type with one member and that member's type?
可以这样做吗?
struct compound_type {
int member;
};
void func()
{
compound_type foo {384};
int bar = sole_member_type_cast<int>(foo); // doesn't compile; there's no such thing
// reinterpret_cast wouldn't compile here
std::cout << bar << std::endl; // prints 384
}
我知道指针别名是可能的,但看起来这是一个严格的别名问题。 (是吗?)联合也被使用,但是你不应该这样做,因为联合类型“一次只能包含一个非静态数据成员”(ref)。
无论如何,这会不会有对齐或偏移问题?
是的,你可以这样做:
int bar = *reinterpret_cast<int*>(&foo);
这是明确定义的,因为 compound_type
和 int
的对象是 pointer-inter-convertible。 foo
的地址与其第一个数据成员的地址相同,即 int
,因此 reinterpret_cast
定义明确。
正如@Remy Lebeau 在评论中指出的那样,转换可以简化为:
int bar = reinterpret_cast<int&>(foo);
更容易阅读和书写。
在具有一个 public non-static 成员的结构和该成员之间进行转换的一种简单方法是使用结构化绑定:
auto [bar] = foo; // auto& to not copy
assert(bar == 384);
这也适用于 non-standard-layout 类型。例如,如果 compound_type::member
是 int&
或 std::vector<int>
,则 &foo
和 &foo.member
将不再是 pointer-interconvertible。
可以这样做吗?
struct compound_type {
int member;
};
void func()
{
compound_type foo {384};
int bar = sole_member_type_cast<int>(foo); // doesn't compile; there's no such thing
// reinterpret_cast wouldn't compile here
std::cout << bar << std::endl; // prints 384
}
我知道指针别名是可能的,但看起来这是一个严格的别名问题。 (是吗?)联合也被使用,但是你不应该这样做,因为联合类型“一次只能包含一个非静态数据成员”(ref)。
无论如何,这会不会有对齐或偏移问题?
是的,你可以这样做:
int bar = *reinterpret_cast<int*>(&foo);
这是明确定义的,因为 compound_type
和 int
的对象是 pointer-inter-convertible。 foo
的地址与其第一个数据成员的地址相同,即 int
,因此 reinterpret_cast
定义明确。
正如@Remy Lebeau 在评论中指出的那样,转换可以简化为:
int bar = reinterpret_cast<int&>(foo);
更容易阅读和书写。
在具有一个 public non-static 成员的结构和该成员之间进行转换的一种简单方法是使用结构化绑定:
auto [bar] = foo; // auto& to not copy
assert(bar == 384);
这也适用于 non-standard-layout 类型。例如,如果 compound_type::member
是 int&
或 std::vector<int>
,则 &foo
和 &foo.member
将不再是 pointer-interconvertible。