如何从boost mp_list提取参数包并用于折叠表达式?
解决boost::mp11过滤后从mp_list提取参数包的优雅方案
你遇到的核心问题是:mp_filter返回的是mp_list<Ts...>类型容器,而非可直接展开的参数包,因此无法直接在折叠表达式中使用。以下是几种比中间lambda模板更简洁的实现方式:
方法1:使用boost::mp11::mp_for_each(最推荐)
mp_for_each是mp11专门为遍历元编程序列设计的工具,直接对每个类型执行操作,无需手动处理参数包展开:
template <typename... MyTypes> class Foo { public: static std::vector<Bar> getBars() { std::vector<Bar> bars; using filtered = boost::mp11::mp_filter<is_barable, boost::mp11::mp_list<MyTypes...>>; // 遍历filtered中的每个类型,执行收集操作 boost::mp11::mp_for_each<filtered>([&bars](auto type_instance) { bars.push_back(decltype(type_instance)::bar()); }); return bars; } };
mp_for_each<filtered>会自动遍历列表中的每个类型,生成对应类型的临时实例type_instance,通过decltype(type_instance)即可拿到原类型,进而调用静态方法bar()。
方法2:使用boost::mp11::mp_apply直接展开参数包
如果确实需要将mp_list转换为参数包来使用折叠表达式,mp_apply可以直接将列表元素展开为参数包传递给可调用对象:
template <typename... MyTypes> class Foo { public: static std::vector<Bar> getBars() { std::vector<Bar> bars; using filtered = boost::mp11::mp_filter<is_barable, boost::mp11::mp_list<MyTypes...>>; // 用mp_apply将mp_list展开为参数包,再通过折叠表达式批量处理 boost::mp11::mp_apply([&bars](auto... type_instances) { (bars.push_back(decltype(type_instances)::bar()), ...); }, filtered{}); return bars; } };
mp_apply会把filtered的所有类型作为参数包传递给lambda,auto... type_instances就是展开后的参数包,后续逻辑和你原有的折叠表达式一致。
方法3:自定义辅助模板(适合复用场景)
如果这个收集逻辑需要在多处使用,可以抽离成独立的辅助模板函数,再通过mp_apply调用:
// 可复用的辅助模板:接收参数包并收集每个类型的bar template <typename... Ts> void collect_barable_types(std::vector<Bar>& bars) { (bars.push_back(Ts::bar()), ...); } template <typename... MyTypes> class Foo { public: static std::vector<Bar> getBars() { std::vector<Bar> bars; using filtered = boost::mp11::mp_filter<is_barable, boost::mp11::mp_list<MyTypes...>>; // 用mp_apply将filtered展开为参数包,传递给辅助函数 boost::mp11::mp_apply<decltype(collect_barable_types), filtered>(bars); return bars; } };
方案对比
你当前使用的C++20模板lambda实现本身是可行的,但上述方法1(mp_for_each)更贴合mp11的设计思路,代码更简洁直观,无需手动定义lambda模板参数,也省去了显式传递mp_list实例的步骤。
内容的提问来源于stack exchange,提问作者rbv
相关产品推荐
相关产品推荐

