使用std::initializer_list构造Col对象的std::vector时编译失败的原因咨询
使用std::initializer_list构造Col对象的std::vector时编译失败的原因咨询
你遇到的问题核心在于std::vector的不同构造函数对类型转换的要求,以及Col类构造函数的explicit修饰符。咱们一步步拆解:
为什么foo函数编译失败?
当你写std::vector<Col> v(data);时,编译器会尝试匹配std::vector的initializer_list构造函数,它的重载签名大致是:
vector(std::initializer_list<T> init, const Allocator& alloc = Allocator());
这个构造函数要求传入的initializer_list元素类型,必须能隐式转换为vector的元素类型(这里是Col)。但你的Col构造函数被explicit修饰了——这个关键字的作用就是禁止隐式转换,所以std::string无法自动转换成Col,导致这个构造函数无法匹配,编译器就抛出了类型不匹配的错误。
为什么bar函数能正常编译?
而std::vector<Col> v(data.begin(), data.end());调用的是std::vector的范围构造函数,签名如下:
template <class InputIt> vector(InputIt first, InputIt last, const Allocator& alloc = Allocator());
这个构造函数会遍历迭代器范围内的每个std::string,然后以直接初始化的方式创建Col对象——直接初始化的场景是允许调用explicit修饰的构造函数的,所以每个std::string都能通过Col(const std::string&)构造出对应的对象,自然编译没问题。
解决办法
如果想让foo函数也能正常工作,有两种可选方案:
- 去掉
Col构造函数的explicit修饰符,这样std::string就能隐式转换为Col,满足initializer_list构造函数的要求; - 手动完成元素转换,比如用
emplace_back逐个构造:void foo(std::initializer_list<std::string> data) { std::vector<Col> v; v.reserve(data.size()); // 提前分配空间提升效率 for (const auto& s : data) { v.emplace_back(s); } }
备注:内容来源于stack exchange,提问作者Abruzzo Forte e Gentile
相关产品推荐
相关产品推荐

