如何将嵌套Param类型层次展平为线性序列,生成对应std::function类型
结论:C20及之前的标准完全可以实现该需求,最低兼容到C11标准即可。
实现思路
核心通过模板偏特化对嵌套的Param类型做递归展开,将所有叶子类型收集到线性类型序列中,最终转换为目标std::function类型,具体实现分为三步:
1. 实现Param类型展平萃取器
递归遍历输入类型,将嵌套的Param展开为std::tuple存储的线性类型序列:
#include <tuple> #include <functional> #include <type_traits> template<class A, class B> struct Param { typedef A A_t; typedef B B_t; }; // 前向声明:展平Param类型的萃取器 template<class T> struct FlattenParam; // 偏特化1:非Param类型视为叶子节点,直接存入tuple template<class T> struct FlattenParam { // 可选:如果要求叶子必须是内置基础类型,可打开以下断言 // static_assert(std::is_fundamental<T>::value, "叶子节点必须为内置基础类型"); using type = std::tuple<T>; }; // 偏特化2:Param类型,递归展平两个模板参数后拼接类型序列 template<class A, class B> struct FlattenParam<Param<A, B>> { private: using flatten_a = typename FlattenParam<A>::type; using flatten_b = typename FlattenParam<B>::type; public: using type = decltype(std::tuple_cat(std::declval<flatten_a>(), std::declval<flatten_b>())); };
2. 实现tuple类型转std::function的辅助模板
将存储线性类型序列的std::tuple转换为对应签名的std::function:
// 辅助模板:将tuple的类型列表转换为void(Args...)签名的function template<class Tuple> struct TupleToFunc; template<class... Args> struct TupleToFunc<std::tuple<Args...>> { using type = std::function<void(Args...)>; };
3. 改写原FuncType模板
template<class P> struct FuncType { using Func_t = typename TupleToFunc<typename FlattenParam<P>::type>::type; };
效果验证
- 非嵌套场景兼容原有实现:
using P1 = Param<float, float>; using Func1 = FuncType<P1>::Func_t; // Func1 类型为 std::function<void(float, float)>,与原行为一致
- 嵌套场景符合预期:
using P2 = Param<float, Param<float, float>>; using Func2 = FuncType<P2>::Func_t; // Func2 类型为 std::function<void(float, float, float)>,可直接匹配void foo(float,float,float)
- 支持任意深度嵌套:
using P3 = Param<Param<int, float>, Param<double, Param<char, bool>>>; using Func3 = FuncType<P3>::Func_t; // Func3 类型为 std::function<void(int, float, double, char, bool)>
内容的提问来源于stack exchange,提问作者ritter
相关产品推荐
相关产品推荐

