2013-08-21 14 views
6

Chciałbym wiedzieć, czy możliwe jest filtrowanie typów przekazanych do szablonu variadic (w oparciu o szablon predykatów) w celu utworzenia kolejnego szablonu variadic zawierającego typy spełniające predykat:Filtrowanie typów pakietów parametrów

/** Filter a parameter pack */  
template <template <class> class, 
      template <class...> class, 
      class...> 
struct filter; 
template <template <class> class Pred, template <class...> class Variadic> 
struct filter<Pred, Variadic> : Variadic<> 
{}; 
template <template <class> class Pred, 
      template <class...> class Variadic, 
      class T, class... Ts> 
struct filter<Pred, Variadic, T, Ts...> 
{ 
    // FIXME: this just stops at first T where Pred<T> is true 
    using type = typename std::conditional< 
     Pred<T>::value, 
     Variadic<T, Ts...>, // can't do: Variadic<T, filter<...>> 
     filter<Pred, Variadic, Ts...> >::type; 
}; 

Jak widać, nie znalazłem sposobu na "wyodrębnienie" pakietu parametrów z pozostałych filtrowanych typów.

Z góry dziękuję!

Odpowiedz

6

To powinno być dość proste. W sercu trzeba mieć coś takiego:

template <typename...> struct filter; 

template <> struct filter<> { using type = std::tuple<>; }; 

template <typename Head, typename ...Tail> 
struct filter<Head, Tail...> 
{ 
    using type = typename std::conditional<Predicate<Head>::value, 
           typename Cons<Head, typename filter<Tail...>::type>::type, 
           typename filter<Tail...>::type 
          >::type; 
}; 

wystarczy Cons<T, Tuple>, która zamienia się std::tuple<T, Args...>T, std::tuple<Args...> i trzeba przejść wzdłuż predykat (pozostawiamy jako ćwiczenie). Cons mógłby wyglądać następująco:

template <typename, typename> struct Cons; 

template <typename T, typename ...Args> 
struct Cons<T, std::tuple<Args...>> 
{ 
    using type = std::tuple<T, Args...>; 
}; 

Wynik filter<Args...>::type byłoby std::tuple<Brgs...>, gdzie Brgs... to pakiet składający się tylko z tych typów w Args... dla którego orzeczenie posiada.

+0

Jest coś, czego nadal nie rozumiem, ale błędy kompilatora nie pomagają. Opublikowalem tutaj http://ideone.com/USTnJR, jesli nie przeszkadza ci przyjmowanie innego spojrzenia - nie wydaje sie odpowiednie do edycji oryginału. – scry

+0

Ta wersja miała inny problem, użyj tego: http://ideone.com/eh3Epd. Jak widać, członkowie filtru i Minusy typu :: nie są rozpoznawani jako typy. – scry

+0

@roysc: 'Wady' powinny być wyspecjalizowane w krotkach. Pozwól mi to edytować. [Edytuj:] Gotowe. Zmieniłem również szablon główny, aby uzyskać prawidłowy podstawowy przypadek. –