You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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>;

逻辑说明

  1. 状态管理:用mp_pair保存折叠过程的状态,第一个元素是当前全局索引,第二个是已生成的外层列表片段
  2. 内层列表处理:
    • 空列表直接保留,不修改索引
    • 非空列表用mp_iota_c生成0到inner_size-1的编译时序列,再通过mp_transform绑定当前索引生成连续的I类型,最后用mp_rename转换成自定义的type_list
  3. 折叠遍历:mp_fold遍历外层列表的每个元素,逐步更新状态,最终取出累积的列表就是目标结果

内容的提问来源于stack exchange,提问作者Chris G.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 14:53:09