C++17中可变参数模板类型运行时遍历的更优雅实现问询
C++17下简化可变参数模板类型遍历的实现方案
针对你从C11迁移到C17时遇到的可变参数模板类型遍历问题,确实可以利用C++17的特性,写出比递归实现简洁得多的代码。
最简洁的实现:直接用初始化列表构造vector
不需要额外辅助函数,直接通过模板参数包展开初始化vector:
template <typename... Ts> std::vector<std::size_t> store_types() { return {typeid(Ts).hash_code()...}; }
这个方案利用了vector的初始化列表构造函数,将参数包Ts中的每个类型对应的typeid(T).hash_code()展开为初始化列表的元素,直接构造并返回vector。相比递归实现,它不仅代码更短,还避免了多次push_back可能带来的内存重新分配,效率更高。
用折叠表达式实现逐个push_back
如果你需要先创建vector再执行其他操作,再添加元素,可以用逗号折叠表达式:
template <typename... Ts> std::vector<std::size_t> store_types() { std::vector<std::size_t> t; (t.push_back(typeid(Ts).hash_code()), ...); return t; }
这里的(表达式, ...)是C++17引入的折叠表达式,它会将参数包中的每个类型代入表达式,展开为连续的逗号操作调用:
// 当Ts为int, double, std::string时,展开后等价于: t.push_back(typeid(int).hash_code()); t.push_back(typeid(double).hash_code()); t.push_back(typeid(std::string).hash_code());
逗号运算符会确保每个push_back都被依次执行。
原无效代码的问题说明
你最初尝试的range-based for循环写法无效,是因为Ts是编译期模板参数包,不是运行时可遍历的容器或序列,无法用普通的for循环遍历。C11及之前只能通过递归模板处理参数包,而C17的折叠表达式和初始化列表展开则完美解决了这个问题。
内容的提问来源于stack exchange,提问作者Caduchon
相关产品推荐
相关产品推荐

