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

使用boost::mp11/brigand时如何判断模板参数是否为typelist

实现方案

boost::mp11和brigand确实没有提供现成的typelist判定工具,不过两个库的typelist都是固定形式的可变参数类模板实例,自己实现类型萃取的成本极低,配合库自带的元算法可以非常简洁地实现你要的分支处理逻辑。

1. 实现typelist判定萃取

两个库的核心typelist定义非常明确:

  • boost::mp11的标准typelist为boost::mp11::mp_list<Ts...>
  • brigand的标准typelist为brigand::list<Ts...>
    直接通过模板偏特化写判定萃取即可,甚至不需要提前包含两个库的全量头文件,只要前置声明对应模板即可:
#include <type_traits>

// 前置声明两个库的list模板
namespace boost { namespace mp11 { template<class...> class mp_list; } }
namespace brigand { template<class...> class list; }

// 基础模板:默认判定为非typelist
template<class T>
struct is_typelist : std::false_type {};

// 匹配mp11的typelist
template<class... Ts>
struct is_typelist<boost::mp11::mp_list<Ts...>> : std::true_type {};

// 匹配brigand的typelist
template<class... Ts>
struct is_typelist<brigand::list<Ts...>> : std::true_type {};

// 便利性变量模板,C++17及以上可用
template<class T>
constexpr bool is_typelist_v = is_typelist<T>::value;

如果后续需要支持其他自定义typelist或者两个库的其他类型集合(比如brigand::set),只要给is_typelist添加对应的偏特化即可,扩展性很好。

2. 整合到factory类的遍历逻辑

不需要手动写递归拆参数包,直接用库自带的元算法把传入的所有参数(不管是单个类型还是typelist)拍平成一个统一的扁平typelist,再统一遍历处理即可,逻辑干净且不容易出错。

mp11版本实现

#include <boost/mp11.hpp>

// 辅助模板:把单个类型转为单元素mp_list,本身是typelist则直接返回
template<class T>
using as_mp_list = std::conditional_t<
    is_typelist_v<T>,
    T,
    boost::mp11::mp_list<T>
>;

template<typename... Types>
class factory
{
    // 把所有传入参数转成list后拼接,再拍平嵌套的typelist
    using flat_types = boost::mp11::mp_flatten<
        boost::mp11::mp_append<as_mp_list<Types>...>
    >;

    // 统一遍历所有展开后的类型
    static void init_registry() {
        boost::mp11::mp_for_each<flat_types>([](auto type_witness) {
            using CurrentType = typename decltype(type_witness)::type;
            // 在这里写单个类型的处理逻辑,比如注册工厂创建函数、生成类型映射等
        });
    }
public:
    factory() {
        init_registry();
    }
};

brigand版本实现

逻辑和mp11版本完全一致,替换成brigand的对应API即可:

#include <brigand/brigand.hpp>

template<class T>
using as_brigand_list = std::conditional_t<
    is_typelist_v<T>,
    T,
    brigand::list<T>
>;

template<typename... Types>
class factory
{
    using flat_types = brigand::flatten<
        brigand::append<as_brigand_list<Types>...>
    >;

    static void init_registry() {
        brigand::for_each<flat_types>([](auto type_witness) {
            using CurrentType = typename decltype(type_witness)::type;
            // 单个类型处理逻辑
        });
    }
public:
    factory() {
        init_registry();
    }
};

补充说明

  • 上述实现默认支持多层嵌套typelist,比如factory<int, mp_list<bool, brigand::list<char, double>>>会被正确展开为int、bool、char、double四个类型依次处理,如果不需要处理嵌套,去掉mp_flatten/brigand::flatten调用即可。
  • 如果你的代码里用了mp11或者brigand的其他类型集合(比如mp11的mp_set、brigand::set),只要给is_typelist增加对应偏特化就能自动适配。
  • 所有你给出的使用示例(factory<int, bool, typelist>、factory<typelist1, int, typelist2>、factory<typelist>)都可以被正确处理,不需要修改调用方代码。

内容的提问来源于stack exchange,提问作者Max Li

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 23:00:55