你能为一个包含 const 成员的联合写一个拷贝构造函数吗?
Can you write a copy constructor for a union with const members?
假设我有一个包含 const
成员的联合的结构,如下所示:
struct S
{
// Members
const enum { NUM, STR } type;
union
{
const int a;
const std::string s;
};
// Constructors
S(int t_a) : type(NUM), a(t_a);
S(const std::string & t_s) : type(STR), s(t_s);
};
到目前为止,还不错。但是现在说我想为这个类型写一个拷贝构造函数。
这似乎并不涉及做任何邪恶的事情,但由于我需要在成员初始值设定项中初始化 const 成员,所以我看不出如何根据依赖于 type
的逻辑来执行此操作会员.
问题:
这个构造函数可以写吗?
如果不是,这本质上是一种语法疏忽,还是有一些根本原因导致语言不能支持这样的事情?
是的,这里可以写拷贝构造函数。实际上它已经在 std::variant
实现中完成,它应该支持 const
类型等。所以你的classS
可以换成
using S = std::variant<const int, const std::string>;
但是如果由于圆顶原因你不能使用 std::variant
那么复制构造函数可以使用 std::construct_at
函数编写如下:
#include <string>
struct S {
const enum { NUM, STR } type;
union {
const int a;
const std::string s;
};
S(int t_a) : type(NUM), a(t_a) {}
S(const std::string & t_s) : type(STR), s(t_s) {}
S(const S & rhs) : type(rhs.type) {
if ( type == NUM ) std::construct_at( &a, rhs.a );
if ( type == STR ) std::construct_at( &s, rhs.s );
}
~S() {
if ( type == STR ) s.~basic_string();
}
};
int main() {
S s(1);
S u = s;
S v("abc");
S w = v;
}
假设我有一个包含 const
成员的联合的结构,如下所示:
struct S
{
// Members
const enum { NUM, STR } type;
union
{
const int a;
const std::string s;
};
// Constructors
S(int t_a) : type(NUM), a(t_a);
S(const std::string & t_s) : type(STR), s(t_s);
};
到目前为止,还不错。但是现在说我想为这个类型写一个拷贝构造函数。
这似乎并不涉及做任何邪恶的事情,但由于我需要在成员初始值设定项中初始化 const 成员,所以我看不出如何根据依赖于 type
的逻辑来执行此操作会员.
问题:
这个构造函数可以写吗?
如果不是,这本质上是一种语法疏忽,还是有一些根本原因导致语言不能支持这样的事情?
是的,这里可以写拷贝构造函数。实际上它已经在 std::variant
实现中完成,它应该支持 const
类型等。所以你的classS
可以换成
using S = std::variant<const int, const std::string>;
但是如果由于圆顶原因你不能使用 std::variant
那么复制构造函数可以使用 std::construct_at
函数编写如下:
#include <string>
struct S {
const enum { NUM, STR } type;
union {
const int a;
const std::string s;
};
S(int t_a) : type(NUM), a(t_a) {}
S(const std::string & t_s) : type(STR), s(t_s) {}
S(const S & rhs) : type(rhs.type) {
if ( type == NUM ) std::construct_at( &a, rhs.a );
if ( type == STR ) std::construct_at( &s, rhs.s );
}
~S() {
if ( type == STR ) s.~basic_string();
}
};
int main() {
S s(1);
S u = s;
S v("abc");
S w = v;
}