模板类模板构造函数调用emplace_back出现编译错误求助
问题描述
我使用fast-cpp-csv-parser库解析CSV文件,因为CSVReader类禁用了拷贝和移动操作,所以想用emplace_back创建并存储CSVReader对象到vector里。但传入emplace_back的参数被CSVReader的模板构造函数识别成了CSVReader类型,导致编译报错。可复现代码如下:
// Type your code here, or load an example. #include <iostream> #include <vector> class LineReader { public: LineReader() = delete; LineReader(const LineReader &) = delete; LineReader &operator=(const LineReader &) = delete; explicit LineReader(const char *file_name) { ; } }; template <unsigned column_count> class CSVReader { private: LineReader in; public: CSVReader() = delete; CSVReader(const CSVReader &) = delete; CSVReader &operator=(const CSVReader &); template <class... Args> explicit CSVReader(Args &&... args) : in(std::forward<Args>(args)...) { } }; int main() { std::vector <CSVReader<12>> vec; vec.emplace_back("hello world"); return 0; }
问题原因与解决方法
问题根源
CSVReader的模板构造函数用了万能引用(Args&&...),而emplace_back的推导逻辑会让编译器尝试匹配所有可能的构造函数。当你传入字符串字面量时,编译器错误地把它推导成了CSVReader<12>类型的右值引用(虽然CSVReader禁用了移动,但模板构造函数的万能引用特性允许这种错误匹配),最终导致编译失败。
修复方案
方案1:显式指定构造函数参数类型
调用emplace_back时,明确告诉编译器要传递的参数类型是const char*,避免错误推导:
vec.emplace_back<const char*>("hello world");
方案2:给模板构造函数添加约束
通过SFINAE机制,限制模板构造函数只能接受能用来构造LineReader的参数,这样编译器就不会误匹配到CSVReader自身类型。修改CSVReader的模板构造函数:
#include <type_traits> template <unsigned column_count> class CSVReader { private: LineReader in; public: CSVReader() = delete; CSVReader(const CSVReader &) = delete; CSVReader &operator=(const CSVReader &); // 添加SFINAE约束 template <class... Args, std::enable_if_t<std::is_constructible_v<LineReader, Args&&...>, bool> = true> explicit CSVReader(Args &&... args) : in(std::forward<Args>(args)...) { } };
内容的提问来源于stack exchange,提问作者Akash
相关产品推荐
相关产品推荐

