如何实现成对类型的参数包?C++模板技术问询
C++实现成对类型参数包展开的方案
你需要在参数包中同时支持成对类型组和单个类型,并分别调用不同函数(baz对应成对类型,bar对应单个类型),最终按逻辑分支返回结果。以下是两种可行的实现方式:
方案一:自定义成对类型封装结构体
先定义一个模板结构体承载成对类型,作为参数包的单个元素:
#include <type_traits> // 自定义成对类型封装 template <typename First, typename Second> struct TypePair { using first_type = First; using second_type = Second; }; // 类型特性:判断是否为自定义成对类型 template <typename T> struct is_type_pair : std::false_type {}; template <typename F, typename S> struct is_type_pair<TypePair<F, S>> : std::true_type {}; template <typename T> constexpr bool is_type_pair_v = is_type_pair<T>::value; // 处理成对类型的辅助函数 template <typename F, typename S> bool process_pair(void* x) { return baz<F, S>(x); } // 处理单个类型的辅助函数 template <typename T> bool process_single(void* x) { return bar<T>(x); } // 主函数模板 template <typename... Args> int foo(void* x) { // 展开所有成对类型的判断 bool has_pair_match = (false || ... || (is_type_pair_v<Args> ? process_pair<typename Args::first_type, typename Args::second_type>(x) : false)); // 展开所有单个类型的判断 bool has_single_match = (false || ... || (is_type_pair_v<Args> ? false : process_single<Args>(x))); if (has_pair_match) return 0; if (has_single_match) return 1; return 2; }
调用方式(对应你预期的伪语法):
// 把伪语法中的{A1,A2}替换为TypePair<A1,A2> foo<TypePair<A1, A2>, TypePair<B1, B2>, C, D>(x);
方案二:利用std::tuple简化封装
不想自定义结构体的话,可直接用C++标准库的std::tuple承载成对类型,省去自定义代码:
#include <tuple> #include <type_traits> // 类型特性:判断是否为二元tuple template <typename T> struct is_binary_tuple : std::false_type {}; template <typename F, typename S> struct is_binary_tuple<std::tuple<F, S>> : std::true_type {}; template <typename T> constexpr bool is_binary_tuple_v = is_binary_tuple<T>::value; // 处理二元tuple的辅助函数 template <typename F, typename S> bool process_tuple(void* x) { return baz<F, S>(x); } // 处理单个类型的辅助函数 template <typename T> bool process_single(void* x) { return bar<T>(x); } // 主函数模板 template <typename... Args> int foo(void* x) { bool has_tuple_match = (false || ... || (is_binary_tuple_v<Args> ? process_tuple<std::tuple_element_t<0, Args>, std::tuple_element_t<1, Args>>(x) : false)); bool has_single_match = (false || ... || (is_binary_tuple_v<Args> ? false : process_single<Args>(x))); if (has_tuple_match) return 0; if (has_single_match) return 1; return 2; }
调用方式:
foo<std::tuple<A1, A2>, std::tuple<B1, B2>, C, D>(x);
关键说明
- 两种方案都利用**类型特性(type trait)**区分参数包中的元素是成对类型还是单个类型
- 使用C++17引入的折叠表达式实现参数包的批量展开,替代递归展开的繁琐写法
- 封装后的成对类型作为参数包的单个元素,完全符合C++模板参数的语法规则
内容的提问来源于stack exchange,提问作者user129393192
相关产品推荐
相关产品推荐

