如何在构造CSVParser时自动推导std::basic_istream模板参数
解决C++20中CSVParser模板参数部分显式指定的问题
要实现仅显式指定Types...而让Ch、Tr从输入流自动推导的需求,C++20的类模板参数推导(CTAD)结合调整模板参数顺序+自定义推导指引就能搞定,具体方案如下:
1. 调整类模板参数顺序
将可变参数Types...移到模板参数列表的最前面,给Ch和Tr设置合理的默认值(确保用户不显式指定时也能正常工作):
#include <iostream> #include <sstream> #include <tuple> #include <charconv> template <typename... Types, typename Ch = char, typename Tr = std::char_traits<Ch>> class CSVParser { public: // 构造函数接收basic_istream引用,用于推导Ch和Tr explicit CSVParser(std::basic_istream<Ch, Tr>& is) : stream_(is) {} // 示例解析函数:读取一行CSV并转换为tuple<Types...> std::tuple<Types...> parse() { std::basic_string<Ch, Tr> line; std::getline(stream_, line); // 此处省略CSV拆分和类型转换的具体实现,仅作示例 std::tuple<Types...> result; // 假设已完成拆分和转换逻辑 return result; } private: std::basic_istream<Ch, Tr>& stream_; };
2. 添加自定义推导指引
为了让编译器从构造函数的basic_istream参数自动推导Ch和Tr,需要补充推导指引:
// 推导指引:从输入流参数推导Ch和Tr,结合用户显式指定的Types... template <typename... Types, typename Ch, typename Tr> CSVParser(std::basic_istream<Ch, Tr>&) -> CSVParser<Types..., Ch, Tr>;
3. 预期用法验证
现在你可以像预想的那样使用CSVParser了:
int main() { std::stringstream ss("123,hello"); // 仅显式指定Types,Ch和Tr自动推导为char、std::char_traits<char> CSVParser<int, std::string> parser(ss); auto data = parser.parse(); // 宽字符流场景同样适用 std::wstringstream wss(L"456,world"); CSVParser<int, std::wstring> wparser(wss); auto wdata = wparser.parse(); return 0; }
关于你之前的报错问题
你提到把可变参数移到开头时编译器报错,大概率是因为原代码中存在依赖Ch/Tr的成员定义(比如basic_istream<Ch, Tr>类型的成员变量)在模板参数列表中Ch/Tr的位置靠后,导致编译器无法解析依赖关系。调整参数顺序后,只要给Ch/Tr设置了合理的默认值,同时确保构造函数的参数能提供足够的推导信息,就能解决这个问题。
内容的提问来源于stack exchange,提问作者TakeoutSpace18
相关产品推荐
相关产品推荐

