基于Boost MPL按constexpr函数返回值排序模板参数包的技术咨询
如何基于特化constexpr函数返回值排序模板参数包
嘿,我完全get到你的需求了——手里攥着近100个用BOOST_STRONG_TYPEDEF定义的强类型,想通过每个类型对应的特化constexpr value_of()返回值,把模板参数包里的类型按这个值做编译期排序对吧?这在编译期元编程里是个挺典型的场景,我给你梳理一套可行的实现方案,一步步来:
第一步:搭好基础结构(强类型+value_of特化)
首先先把你的强类型定义和对应的value_of特化写好,这里用几个示例类型演示:
#include <boost/strong_typedef.hpp> #include <cstddef> #include <type_traits> #include <tuple> // 示例强类型(你实际有近100个类似定义) BOOST_STRONG_TYPEDEF(TYPE_1, int) BOOST_STRONG_TYPEDEF(TYPE_2, double) BOOST_STRONG_TYPEDEF(TYPE_3, uint8_t) BOOST_STRONG_TYPEDEF(TYPE_4, float) // 通用模板(默认删除,确保只使用特化版本,避免误用) template<typename T> constexpr size_t value_of() = delete; // 为每个强类型特化value_of,返回你需要的排序权重 template<> constexpr size_t value_of<TYPE_1>() { return 3; } template<> constexpr size_t value_of<TYPE_2>() { return 1; } template<> constexpr size_t value_of<TYPE_3>() { return 4; } template<> constexpr size_t value_of<TYPE_4>() { return 2; }
第二步:实现编译期类型比较逻辑
我们需要一个编译期的工具,用来判断两个类型的value_of返回值大小关系:
// 编译期判断:类型A的权重是否小于类型B template<typename A, typename B> constexpr bool is_less() { return value_of<A>() < value_of<B>(); }
第三步:实现编译期插入排序元函数
插入排序是编译期处理类型列表比较直观的算法——我们先维护一个已排序的类型列表,然后逐个把新类型插入到合适的位置。这里我们用自定义的type_list来承载类型集合(你也可以用std::tuple替代,逻辑类似):
// 自定义类型列表结构体 template<typename... Ts> struct type_list {}; // 辅助元函数:将类型T插入到已排序的类型列表SortedList中 template<typename T, typename SortedList> struct insert_sorted; // 基础情况:插入到空列表 template<typename T> struct insert_sorted<T, type_list<>> { using type = type_list<T>; }; // 递归情况:根据权重决定插入位置 template<typename T, typename First, typename... Rest> struct insert_sorted<T, type_list<First, Rest...>> { using type = typename std::conditional< is_less<T, First>(), type_list<T, First, Rest...>, type_list<First, typename insert_sorted<T, type_list<Rest...>>::type> >::type; };
第四步:构建完整的参数包排序元函数
接下来我们把整个参数包拆解,递归地将每个类型插入到已排序列表中:
// 核心排序元函数:对模板参数包Ts排序 template<typename... Ts> struct sort_types; // 基础情况:空参数包返回空列表 template<> struct sort_types<> { using type = type_list<>; }; // 递归情况:把第一个类型插入到剩余类型排序后的列表中 template<typename First, typename... Rest> struct sort_types<First, Rest...> { using sorted_rest = typename sort_types<Rest...>::type; using type = typename insert_sorted<First, sorted_rest>::type; }; // 便捷别名,简化使用 template<typename... Ts> using sort_types_t = typename sort_types<Ts...>::type;
第五步:测试验证排序结果
最后我们可以用static_assert来验证排序是否符合预期:
// 对示例类型包排序 using sorted_type_list = sort_types_t<TYPE_1, TYPE_2, TYPE_3, TYPE_4>; // 验证排序结果:按权重1→2→3→4对应TYPE_2→TYPE_4→TYPE_1→TYPE_3 static_assert(std::is_same_v<sorted_type_list, type_list<TYPE_2, TYPE_4, TYPE_1, TYPE_3>>);
额外注意事项
- 如果你更习惯用
std::tuple承载类型,只需要把type_list替换成std::tuple,调整insert_sorted的逻辑即可,核心思路完全一致。 - 这个实现是稳定排序:如果两个类型的
value_of返回值相同,它们在参数包中的相对顺序会被保留。如果需要不稳定排序,只需要把is_less的条件改成value_of<A>() <= value_of<B>()即可。 - 对于近100个类型的参数包,编译期排序的开销完全在编译器可承受范围内,不用担心性能问题。
内容的提问来源于stack exchange,提问作者user3831357
相关产品推荐
相关产品推荐

