std::variant如何通过初始化列表完成初始化?
std::variant 花括号初始化失效问题说明
问题根因
你遇到的写法失效,本质是std::variant的构造规则决定的:
当传入的初始化参数是无明确类型的裸花括号列表时,编译器不会自动遍历variant内部的所有候选存储类型,去推导哪个类型可以匹配该列表结构。
直接初始化普通std::map时,目标类型是完全确定的,编译器可以顺着map的构造逻辑解析花括号内容;换成variant之后,裸花括号没有可匹配的明确类型锚点,自然无法触发对应的构造流程,最终报类型不匹配的编译错误。
纯裸初始化列表是否可行
完全依靠无任何类型标注的嵌套花括号完成初始化是做不到的。这是C++标准对std::variant的固定设计行为——为了避免无意义的重载歧义,从语言层面就禁止了编译器对裸花括号列表做跨候选类型的自动匹配推导。
最优初始化实现方案
按照工程实践中的通用优先级,三类无歧义、低开销的实现方式如下:
- 【标准推荐、零开销】使用
std::in_place_type标签显式指定要初始化的内部类型:
标签会作为编译期的明确标记,告诉编译器要初始化variant中存储的std::variant<std::map<int, double>, int> b( std::in_place_type<std::map<int, double>>, {{1, 0.1}} );std::map<int, double>类型,后续传入的花括号列表可以被map的构造函数正常解析,全程无临时对象、无多余赋值开销。 - 【可读性最高】显式构造目标类型实例后再赋值给variant:
写法直白清晰,不会给阅读代码的人造成任何理解障碍,编译过程无歧义。std::variant<std::map<int, double>, int> b = std::map<int, double>{{1, 0.1}}; - 【适合延迟初始化】使用
emplace接口直接构造内部存储:// 先声明空的variant实例 std::variant<std::map<int, double>, int> b; // 直接在variant的存储内存上构造目标类型,避开临时对象拷贝 b.emplace<std::map<int, double>>({1, 0.1});
内容的提问来源于stack exchange,提问作者stanleyli
相关产品推荐
相关产品推荐

