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

时间:2016-09-12 09:24:49

标签: c++ c++14 boost-hana

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

#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;
}

基本上我想要的是: 我有一个类型列表,我想返回一个列表,其中包含不在filterlist中的项目。所以在这种情况下,它应该是std::tuple<Y, Z>

该计划的当前输出是: 筛选列表包含3个项目,预计2个项目

问候,Matthijs

1 个答案:

答案 0 :(得分:3)

问题在于您正在检查过滤器列表中是否包含类型(decltype_(X{}) == type<X>{}),其中包含实际对象,而不是类型。换句话说,有点像你试图将表示某种类型std::type_info的{​​{1}}对象与实际类型为T的对象进行比较;这在语义上毫无意义。相反,你想要的是以下内容:

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

作为最后一点,请注意这些结构,因为它们是O(n ^ 2)编译时。如果你需要有效的查找,请考虑使用#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; } (现在实现很糟糕,但是当我有更多时间时它会变得更好)。