使用 boost::hana 过滤具有类型的列表

Posted

技术标签:

【中文标题】使用 boost::hana 过滤具有类型的列表【英文标题】:Filtering a list with types using boost::hana 【发布时间】:2016-09-12 09:24:49 【问题描述】:

我正在尝试过滤掉带有类型的列表,但这似乎不起作用。我确定我在这里做错了,这是我为重现它而创建的测试:

#include <iostream>

#include <boost/hana.hpp>
#include <boost/hana/ext/std/tuple.hpp>

struct X 
;
struct Y 
;
struct Z 
;

int main(int argc, char **argv) 

    namespace hana = boost::hana;

    constexpr std::tuple<X, Y, Z> list;
    constexpr std::tuple<X> filterlist;

    auto t = hana::filter(list, [&](auto t) 
            return hana::not_(hana::contains(filterlist, hana::decltype_(t)));
        );

    std::cout << "filtered list contains " << hana::size(t) << " items, expected 2 items" << std::endl;

    return 0;

基本上我想要的: 我有一个类型列表,我想返回一个包含不在过滤器列表中的项目的列表。所以在这种情况下,应该是std::tuple&lt;Y, Z&gt;

这个程序的当前输出是: 过滤后的列表包含 3 项,预计为 2 项

问候,马蒂斯

【问题讨论】:

【参考方案1】:

问题是您正在检查一个类型 (decltype_(X) == type&lt;X&gt;) 是否在过滤器列表中,该列表包含实际对象,而不是类型。换句话说,这有点像您试图将表示某种类型Tstd::type_info 对象与实际类型T 的对象进行比较;这在语义上没有意义。相反,您想要的是以下内容:

#include <iostream>
#include <boost/hana.hpp>
#include <boost/hana/ext/std/tuple.hpp>
namespace hana = boost::hana;

struct X  ;
struct Y  ;
struct Z  ;

int main(int argc, char **argv) 
  constexpr std::tuple<X, Y, Z> list;
  constexpr std::tuple<hana::type<X>> filterlist;
  auto t = hana::remove_if(list, [&](auto t) 
    return hana::contains(filterlist, hana::decltype_(t));
  );

  std::cout << "filtered list contains " << hana::size(t) << " items, expected 2 items" << std::endl;

话虽如此,如果您已经有一个 filterlist 元组用于其他目的,您仍然可以使用它进行过滤:

#include <iostream>
#include <boost/hana.hpp>
#include <boost/hana/ext/std/tuple.hpp>
namespace hana = boost::hana;

struct X  ;
struct Y  ;
struct Z  ;

int main(int argc, char **argv) 
  constexpr std::tuple<X, Y, Z> list;
  constexpr std::tuple<X> filterlist;
  auto t = hana::remove_if(list, [&](auto t) 
    return hana::any_of(filterlist, [&](auto u) 
        return hana::decltype_(u) == hana::decltype_(t);
    );
  );

  std::cout << "filtered list contains " << hana::size(t) << " items, expected 2 items" << std::endl;

最后一点,请注意这些构造,因为它们是 O(n^2) 编译时间。如果您需要高效的查找,请考虑使用hana::set(现在的实现很糟糕,但我有更多时间会变得更好)。

【讨论】:

以上是关于使用 boost::hana 过滤具有类型的列表的主要内容,如果未能解决你的问题,请参考以下文章

Boost Hana 编译时列表转换

Boost hana 获取字符串类型

Boost.Hana在visual studio 2017 rc中的残缺使用

如何将 boost::hana::tuple 转换为 std::variant

如何使用underscore.js在列表元素中过滤具有匹配参数的对象?

减轻头文件中的长限定