2016-09-12 1 views
1

J'essaie de filtrer une liste avec des types, mais cela ne semble pas fonctionner. Je suis sûr que je fais quelque chose de mal ici, voici un test que je l'ai créé pour reproduire:Filtrer une liste avec des types utilisant 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; 
} 

Au fond ce que je veux: J'ai une liste des types et je veux retourner une liste éléments qui ne sont pas dans la liste de filtres. Donc, dans ce cas, il devrait être std::tuple<Y, Z>.

La sortie actuelle de ce programme est: liste filtrée contient 3 éléments, attendu 2 articles

Cordialement, Matthijs

Répondre

3

Le problème est que vous vérifiez si un type (decltype_(X{}) == type<X>{}) est dans la liste de filtres, qui contient des objets réels, pas des types. En d'autres termes, c'est un peu comme si vous essayiez de comparer un objet std::type_info représentant un certain type T avec un objet du type réel T; cela n'a aucun sens sémantiquement. Au lieu de cela, ce que vous voulez est la suivante:

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

Cela dit, si vous avez déjà un filterlist tuple qui est autour de toute façon à d'autres fins, vous pouvez toujours l'utiliser pour filtrer:

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

Comme une dernière note, méfiez-vous de ces constructions puisqu'elles sont O (n^2) à la compilation. Si vous avez besoin d'une recherche efficace, pensez à utiliser hana::set (l'implémentation est mauvaise maintenant mais elle ira mieux si j'ai plus de temps).