如何在unordered_map的try_emplace中正确构造自定义类型?
问题分析
你调用try_emplace时传递的1,1,3是三个int参数,但bar是聚合类型,仅包含int c和foo f两个成员,编译器找不到接受三个int的bar构造函数,因此抛出匹配错误。
解决方案
以下几种方式可以解决编译问题:
方案1:给bar添加构造函数
通过显式构造函数,让try_emplace的参数能匹配到合法的构造逻辑:
#include <iostream> #include <unordered_map> using namespace std; struct foo { int a; int b; }; struct bar { int c; foo f; // 构造函数1:接收int和foo对象 bar(int c_, foo f_) : c(c_), f(f_) {} // 构造函数2:直接接收三个int,拆分初始化c和foo的成员 bar(int c_, int a_, int b_) : c(c_), f{a_, b_} {} }; int main() { unordered_map<string, bar> map; // 使用构造函数1 map.try_emplace("hi", 1, foo{1, 3}); // 使用构造函数2 map.try_emplace("hello", 2, 4, 5); return 0; }
方案2:直接传递bar的聚合初始化实例(C++17+)
如果不想修改结构体定义,在C++17及以上标准中,可以直接传递已初始化的bar对象:
int main() { unordered_map<string, bar> map; // 显式构造bar对象 map.try_emplace("hi", bar{1, foo{1, 3}}); // 更简洁的聚合初始化写法 map.try_emplace("hello", bar{2, {4, 5}}); return 0; }
方案3:用std::forward_as_tuple传递聚合参数(C++17+)
保持bar的聚合类型特性,通过元组传递初始化参数:
#include <tuple> // 需要包含tuple头文件 int main() { unordered_map<string, bar> map; map.try_emplace("hi", std::forward_as_tuple(1, foo{1, 3})); return 0; }
补充说明
你之前尝试的map.try_emplace("hi", 1, {1, 3})失败,是因为旧版本C++标准中,编译器无法将初始化列表{1,3}作为函数参数推导为foo类型,因此需要显式构造foo对象或使用上述方案规避。
内容的提问来源于stack exchange,提问作者rookie
相关产品推荐
相关产品推荐

