如何用boost::mp11将编译时类型列表列表转为索引列表列表?
使用Boost.MP11实现编译时二维iota类型转换
需求清晰:将编译时嵌套的type_list结构,把非空内层列表的每个元素替换为连续递增的std::integral_constant索引,空列表保持不变,类似二维iota的生成逻辑。
输入示例
template<typename... Ts> struct type_list{}; using L = type_list< type_list<>, type_list<>, type_list<>, type_list<>, type_list<int>, type_list<>, type_list<int>, type_list<int>, type_list<int>, type_list<int,double>, type_list<int,double> >;
期望输出
template<uint64_t V> using I = std::integral_constant<uint64_t, V>; // 简化书写的别名 using R = type_list< type_list<>, type_list<>, type_list<>, type_list<>, type_list<I<0>>, type_list<>, type_list<I<1>>, type_list<I<2>>, type_list<I<3>>, type_list<I<4>, I<5>>, type_list<I<6>, I<7>> >;
实现方案(简化版)
借助Boost.MP11的元编程工具,通过折叠遍历维护全局索引,同时对每个内层列表做元素替换,代码简洁高效:
#include <boost/mp11/mp11.hpp> #include <cstdint> #include <type_traits> namespace mp = boost::mp11; // 基础类型定义 template<typename... Ts> struct type_list{}; template<uint64_t V> using I = std::integral_constant<uint64_t, V>; // 折叠遍历的单步处理逻辑:输入状态(当前索引, 累积列表),返回新状态(更新后索引, 更新后列表) template<typename State, typename InnerList> struct process_step { // 提取当前索引值 static constexpr uint64_t current_idx = mp::mp_first<State>::value; // 获取内层列表的元素数量 static constexpr std::size_t inner_size = mp::mp_size<InnerList>::value; // 生成转换后的内层列表:空列表直接保留,非空则生成连续索引的I类型列表 using converted_inner = std::conditional_t< inner_size == 0, InnerList, mp::mp_rename<mp::mp_transform<mp::mp_bind_front<I, current_idx>, mp::mp_iota_c<inner_size>>, type_list> >; // 更新累积列表:追加转换后的内层列表 using new_accumulated_list = mp::mp_push_back<mp::mp_second<State>, converted_inner>; // 更新索引:累加当前内层列表的元素数量 using new_idx = std::integral_constant<uint64_t, current_idx + inner_size>; // 封装新状态 using type = mp::mp_pair<new_idx, new_accumulated_list>; }; // 最终转换的别名模板:通过mp_fold完成遍历,提取最终的累积列表 template<typename OuterList> using convert_to_index_lists_t = mp::mp_second< mp::mp_fold< OuterList, mp::mp_pair<std::integral_constant<uint64_t, 0>, type_list<>>, // 初始状态:索引0+空列表 process_step > >; // 测试使用 using L = type_list< type_list<>, type_list<>, type_list<>, type_list<>, type_list<int>, type_list<>, type_list<int>, type_list<int>, type_list<int>, type_list<int,double>, type_list<int,double> >; // 得到目标结果R using R = convert_to_index_lists_t<L>;
逻辑说明
- 状态管理:用
mp_pair保存折叠过程的状态,第一个元素是当前全局索引,第二个是已生成的外层列表片段 - 内层列表处理:
- 空列表直接保留,不修改索引
- 非空列表用
mp_iota_c生成0到inner_size-1的编译时序列,再通过mp_transform绑定当前索引生成连续的I类型,最后用mp_rename转换成自定义的type_list
- 折叠遍历:
mp_fold遍历外层列表的每个元素,逐步更新状态,最终取出累积的列表就是目标结果
内容的提问来源于stack exchange,提问作者Chris G.
相关产品推荐
相关产品推荐

