如何通过类型派生过滤可变参数模板包?

dvi*_*ino 3 c++ templates variadic-templates c++11

我有一个接收多种类型的模板类,接收到的每种类型都是两个选项之一的子类。我想根据标识它们的父类以不同的方式扩展它们。这相当于对可变参数模板参数实现“过滤器”。

例如:

class A{};
class B{};

template<class... C>
struct F{
     std::tuple<types_derived_by<A, C>...> fn(types_subclassing<B, C>...){}
};
Run Code Online (Sandbox Code Playgroud)

types_衍生_by 模板函数应该生成一个可变参数模板包,其中包含 C 中从 A 或 B 派生的所有类型。

例如:

struct DA : public A{};
struct DB : public B{};
int main(){
    F<DA, DB> f;
    //f has a member function: DA fn(DB);

}
Run Code Online (Sandbox Code Playgroud)

我正在使用 C++11,但如果有必要,我可以迁移到 c++14。

Jar*_*d42 5

你可以这样做:

template <template <typename> class Pred, typename TUPLE, typename Res = std::tuple<>>
struct Filter;

template <template <typename> class Pred, typename Res> 
struct Filter<Pred, std::tuple<>, Res>
{
    using type = Res;
};

template <template <typename> class Pred, typename T, typename ... Ts, typename ... TRes> 
struct Filter<Pred, std::tuple<T, Ts...>, std::tuple<TRes...>> :
    Filter<Pred,
           std::tuple<Ts...>,
           std::conditional_t<Pred<T>::value,
                              std::tuple<TRes..., T>,
                              std::tuple<TRes...>>>
{
};
Run Code Online (Sandbox Code Playgroud)

或者,使用std::tuple_cat

template <template <typename> class Pred, typename TUPLE>
struct Filter;

template <template <typename> class Pred, typename ... Ts> 
struct Filter<Pred, std::tuple<Ts...>>
{
    using type = decltype(std::tuple_cat(
           std::declval<std::conditional_t<Pred<Ts>::value,
                                           std::tuple<Ts>,
                                           std::tuple<>>>()...));
};
Run Code Online (Sandbox Code Playgroud)

进而:

class A {};
template <typename T>
using is_base_of_A = std::is_base_of<A, T>;

class B {};
struct DA : public A{};
struct DB : public B{};
struct DA1 : public A{};

static_assert(std::is_same<std::tuple<DA, DA1>,
                           Filter<is_base_of_A, std::tuple<DA, DB, DA1>>::type>::value,
              "unexpected");
Run Code Online (Sandbox Code Playgroud)

演示/ 演示与std::tuple_cat