如何在C++模板元编程中用boost::mp11从mp_list条件提取类型生成新列表?
使用Boost.Mp11实现按标签筛选并生成类型列表
需求背景
给定带标签的类型集合TypePool与标签筛选列表filter,需从TypePool中筛选每个标签对应的类型,按filter顺序将这些类型组合,生成所有可能的类型列表(若某标签对应多个类型,每个类型需分别与其他标签的单个类型组合成新列表)。
原始定义代码如下:
#include <boost/mp11/mp_list.hpp> #include <boost/mp11/mp_int.hpp> #include <cstdint> // 基础类型定义 template<typename tag, uint32_t _data> struct DType { using typeTag = tag; uint32_t payload = _data; }; template<typename tag> struct AType { using typeTag = tag; int32_t process() { return 0; }; }; template<typename tag> struct VType { using typeTag = tag; bool verify() { return true; }; }; // 类型标签定义 using inputA = boost::mp11::mp_int<0>; using inputB = boost::mp11::mp_int<1>; using ProcA = boost::mp11::mp_int<2>; using ProcB = boost::mp11::mp_int<3>; using VrfyA = boost::mp11::mp_int<4>; // 类型池 using TypePool = boost::mp11::mp_list< DType<inputA, 0>, DType<inputB, 1>, DType<inputB, 2>, AType<ProcA>, AType<ProcB>, VType<VrfyA> >; // 筛选标签列表 using filter = boost::mp11::mp_list<inputB, ProcA, VrfyA>; // 期望生成的结果示例 using list1 = boost::mp11::mp_list<DType<inputB, 1>, AType<ProcA>, VType<VrfyA>>; using list2 = boost::mp11::mp_list<DType<inputB, 2>, AType<ProcA>, VType<VrfyA>>;
实现方案
步骤1:定义类型标签匹配谓词
实现元函数判断类型是否带有指定标签:
#include <boost/mp11/mp_same.hpp> #include <boost/mp11/mp_filter.hpp> #include <boost/mp11/mp_transform.hpp> #include <boost/mp11/mp_bind.hpp> #include <boost/mp11/mp_cartesian_product.hpp> template<typename Tag> struct HasTypeTag { template<typename T> using fn = boost::mp11::mp_same<typename T::typeTag, Tag>; };
步骤2:按筛选标签提取对应类型列表
用mp_transform和mp_filter为每个筛选标签提取匹配类型,得到由类型列表组成的新列表:
// 每个筛选标签对应的类型列表组成的列表 using FilteredLists = boost::mp11::mp_transform< boost::mp11::mp_bind_front<boost::mp11::mp_filter, HasTypeTag<>::fn>, filter >;
此时FilteredLists的实际类型为:
boost::mp11::mp_list< boost::mp11::mp_list<DType<inputB, 1>, DType<inputB, 2>>, boost::mp11::mp_list<AType<ProcA>>, boost::mp11::mp_list<VType<VrfyA>> >;
步骤3:计算类型列表的笛卡尔积
利用mp_cartesian_product计算上述列表的笛卡尔积,得到所有符合要求的组合列表:
// 最终生成的所有组合列表 using ResultLists = boost::mp11::mp_cartesian_product<FilteredLists>;
结果验证
ResultLists包含所有目标组合,可通过静态断言验证:
static_assert(boost::mp11::mp_same<boost::mp11::mp_first<ResultLists>, list1>::value, "Mismatch"); static_assert(boost::mp11::mp_same<boost::mp11::mp_second<ResultLists>, list2>::value, "Mismatch");
内容的提问来源于stack exchange,提问作者neuron mac
相关产品推荐
相关产品推荐

