Фильтрация типов пакета параметров

Я хотел бы знать, можно ли фильтровать типы, переданные в вариационный шаблон (на основе шаблона предиката), для создания другого вариационного шаблона, содержащего те типы, которые удовлетворяют предикату:

/** 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;
};

<p>Как вы можете видеть, я не нашел способ "извлечь" пакет параметров из остальных фильтрованных типов.</p>
<p>Спасибо заранее!</p></pred,></t,></t,></t></t></pred,></class...></template></pred,></class...></template></class...></template>
1 ответ

Это должно быть довольно прямолинейно. В глубине души у вас должно быть что-то вроде этого:

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;
};
</tail...></head,></predicate<head></head,></typename></typename...>

Вам просто нужно Cons, которое превращает T, std::tuple в std::tuple, и вам нужно передать предикат (слева как упражнение). Cons может выглядеть так:

template <typename, typename=""> struct Cons;
template <typename t,="" typename="" ...args="">
struct Cons<t, std::tuple<args...="">>
{
 using type = std::tuple<t, args...="">;
};
</t,></t,></typename></typename,>

Результат filter<args...>::type</args...> будет std::tuple, где Brgs... представляет собой пакет, состоящий только из тех типов в Args..., для которых выполняется предикат.

licensed under cc by-sa 3.0 with attribution.