使用boost::hana过滤类型列表

Filtering a list with types using boost::hana

本文关键字:类型 列表 过滤 hana boost 使用      更新时间:2023-10-16

我试图过滤出一个列表的类型,但这似乎不工作。我确定我在这里做错了什么,这里是我创建的一个测试来复制它:

#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<Y, Z>

程序的当前输出为:筛选列表包含3项,预期2项

问候,Matthijs

问题是您正在检查类型(decltype_(X{}) == type<X>{})是否在过滤器列表中,该列表包含实际对象,而不是类型。换句话说,这有点像你试图将代表某种类型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(现在的实现很糟糕,但当我有更多的时间时,它会变得更好)。