定义一个类`MultiInherit <MyTuple <X1,X2,... >>`来继承自`X1,X2,...`

jav*_*ver 2 c++ variadic-templates c++14

如何定义MultiInherit<MyTuple<X1,X2,...>>要继承的类X1,X2,...
我想传递MyTuple<X1,X2,...>一个新的对象类型。

template <class... Xs> class MyTuple{};
template <class MyTupleXs> class MultiInherit : public All_Xs_in_MyTupleXs { //??

};
Run Code Online (Sandbox Code Playgroud)

这是它的用法和MCVE(不可编译):

class B{public: int b;};
class C{public: int c;};
class BC : public MultiInherit<MyTuple<B,C>> {
    public: void testCompile(){
        this->b=this->c;   
    }
};
int main(){
}
Run Code Online (Sandbox Code Playgroud)

尝试1

以下是最接近我想要的东西。
如果我得到的原始类型(例如B,C)为模板argumant而不是MyTuple<B,C>,它会很容易: -
MCVE,编译)

template <class... Xs> class MultiInherit : public Xs... { 
};
class B{public: int b;};
class C{public: int c;};
class BC : public MultiInherit<B,C> {
    public: void testCompile(){
        this->b=this->c;   
    }
};  
Run Code Online (Sandbox Code Playgroud)

参考:c ++ 11中的可变参数模板和多重继承
无法解决。我想传递一个封装的类型MyTuple<B,C>,而不是B,C

尝试2

我考虑过MyXsMyTuple:-中添加新的可变参数typedef

template <class... Xs> class MyTuple{
   public: using MyXs=Xs...;    
};
template <class MyTupleXs> class MultiInherit : public MyTupleXs::MyXs { 
};
Run Code Online (Sandbox Code Playgroud)

但是,在我看来,该语言没有这种功能。

(我是可变参数模板的新手。)

J. *_*rez 5

简单的答案

您必须创建的模板专用MultiInherit。让我们看一下的基本情况MultiInherit

template<class... Xs> 
class MultiInherit : public Xs... {
    // Stuff
}; 
Run Code Online (Sandbox Code Playgroud)

在这里,我们采用一堆类型并从它们继承。但是我们可以使用模板专门化来解压缩元组:

// Specialization on MyTuple
template<class... Xs> 
class MultiInherit<MyTuple<Xs...>> : public Xs... {
     // Stuff
};
Run Code Online (Sandbox Code Playgroud)

这使您可以做自己想做的。给定一个MyTuple,您有一个MultiInherit从所有成员继承的类。

更一般的情况

定义类型列表。如果您想更一般地进行操作,则根据代表类型列表的模板来进行操作会很有用。我们可以定义一个模板来表示类型列表:

template<class...>
struct TypeList {}; 
Run Code Online (Sandbox Code Playgroud)

串联类型列表。我们可以定义更多模板来连接类型列表。ConcatLists是一个具有两个类型列表的函数,并返回将TypeList它们串联在一起的a:

template<class... Xs, class... Ys>
TypeList<Xs..., Ys...> ConcatLists(TypeList<Xs...>, TypeList<Ys...>) {
    return {}; 
}
Run Code Online (Sandbox Code Playgroud)

我们可以使用它来定义一个concat_t自动执行的操作:

template<class TypeListA, class TypeListB>
using concat_t = decltype(ConcatLists(TypeListA{}, TypeListB{})); 
Run Code Online (Sandbox Code Playgroud)

MultiInheritTypeList我们还可以使用模板专业化功能将一种类型替换为另一种类型。

// Base case
template<template<class...> class Replacement, class List>
struct SubstituteList;

template<
    template<class...> class Replacement, 
    template<class...> class Original,
    class... Xs>
struct SubstituteList<Replacement, Original<Xs...>> {
    using type = Replacement<Xs...>;
};

template<template<class...> class Replacement, class List>
using substitute_list_t = typename SubstituteList<Replacement, List>::type; 
Run Code Online (Sandbox Code Playgroud)

这意味着您可以将TypeList替换为MultiInherit

template<class ListOfTypes>
using MultiInheritFromTypeList = substitute_list_t<MultiInherit, ListOfTypes>; 
Run Code Online (Sandbox Code Playgroud)

用法示例。如果要将a转换TypeListMultiInherit

using T1 = TypeList<int, char, bool>;
// T2 is MultiInherit<int, char, bool>;
using T2 = MultiInheritFromTypeList<T1>;
Run Code Online (Sandbox Code Playgroud)

以concat为例。或者,如果要连接多个TypeLists并将其转换为MultiInherit

using T1 = TypeList<int, char, bool>;
using T2 = TypeList<double, float>;
// T3 is MuliInherit<int, char, bool, double, float>
using T3 = MultiInheritFromTypeList<concat_t<T1, T2>>;
Run Code Online (Sandbox Code Playgroud)