如何使用初始化列表初始化包含自定义类variant的std::array
问题解决方法
问题根源
- 你的
Vector类仅显式声明了constexpr移动构造函数,根据C++标准,当用户自定义移动构造函数后,编译器不会自动生成默认拷贝构造函数,拷贝构造会被隐式置为删除状态。 - 单独给
std::variant赋值时,编译器走直接初始化路径,使用移动构造即可完成转换,因此可以正常运行。 - 用初始化列表初始化承载
std::variant的std::array时,MSVC的重载解析逻辑会优先尝试拷贝构造路径,发现拷贝构造不可用后没有正确回退到移动构造路径,因此抛出转换错误。
修复方案
- 首先给
Vector类补全默认constexpr拷贝构造函数:
constexpr Vector(const Vector& s) = default;
- (可选优化)在初始化
std::array时对参数使用std::move,触发移动构造规避拷贝开销,同时避免部分重载解析歧义,在Cast函数中修改初始化语句为:
std::array<MsgArg, COUNT> rgArgs = { std::move(args)... };
- (可选)如果初始化列表中存在数值常量,显式转换为
variant匹配的类型,避免类型推导歧义,比如示例中的0U显式转成unsigned char:
std::array<gmsgGiveWpn::MsgArg, 2> v = { Vector(1, 1, 1), static_cast<unsigned char>(0U) };
完成以上修改后即可在VS2022/C++20的MSVC环境下正常编译。
内容的提问来源于stack exchange,提问作者Hydrogen
相关产品推荐
相关产品推荐

