定义一个 class `MultiInherit<MyTuple<X1,X2,...>>` 以继承自 `X1,X2,...`
define a class `MultiInherit<MyTuple<X1,X2,...>>` to inherit from `X1,X2,...`
如何定义一个class MultiInherit<MyTuple<X1,X2,...>>
继承自X1,X2,...
?
我想传递 MyTuple<X1,X2,...>
来组成一个新的对象类型。
template <class... Xs> class MyTuple{};
template <class MyTupleXs> class MultiInherit : public All_Xs_in_MyTupleXs { //??
};
这是它的用法和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(){
}
尝试 1
下面是最接近我想要的。
如果我得到原始类型(例如 B,C
)作为模板参数而不是 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;
}
};
参考:
这不解决。我想传递一个封装类型 MyTuple<B,C>
,而不是 B,C
.
尝试 2
我想在 MyTuple
中添加一个新的可变类型定义 MyXs
:-
template <class... Xs> class MyTuple{
public: using MyXs=Xs...;
};
template <class MyTupleXs> class MultiInherit : public MyTupleXs::MyXs {
};
然而,在我看来,该语言没有这样的功能。
(我是可变参数模板的新手。)
简单回答
您必须 create a template specialization 个 MultiInherit
。让我们看看 MultiInherit
:
的基本情况
template<class... Xs>
class MultiInherit : public Xs... {
// Stuff
};
在这里,我们采用了一堆类型并继承了它们。但是我们可以使用模板特化来解包元组:
// Specialization on MyTuple
template<class... Xs>
class MultiInherit<MyTuple<Xs...>> : public Xs... {
// Stuff
};
这让您可以随心所欲。给定一个 MyTuple
,你有一个继承自所有成员的 MultiInherit
class。
更一般的情况
定义类型列表。如果您想做一些更一般的事情,基于表示类型列表的模板来做它们会很有用。我们可以定义一个模板来表示一个类型列表:
template<class...>
struct TypeList {};
连接类型列表。我们可以定义更多模板来连接类型列表。 ConcatLists
是一个接受两个类型列表的函数,returns 一个 TypeList
连接它们:
template<class... Xs, class... Ys>
TypeList<Xs..., Ys...> ConcatLists(TypeList<Xs...>, TypeList<Ys...>) {
return {};
}
我们可以使用它来定义一个自动执行此操作的 concat_t
:
template<class TypeListA, class TypeListB>
using concat_t = decltype(ConcatLists(TypeListA{}, TypeListB{}));
用MultiInherit
代替TypeList
。 我们还可以使用模板特化用一种类型代替另一种类型。
// 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;
这意味着您可以将 TypeList
替换为 MultiInherit
:
template<class ListOfTypes>
using MultiInheritFromTypeList = substitute_list_t<MultiInherit, ListOfTypes>;
用法示例。 如果要将 TypeList
转换为 MultiInherit
:
using T1 = TypeList<int, char, bool>;
// T2 is MultiInherit<int, char, bool>;
using T2 = MultiInheritFromTypeList<T1>;
concat 示例。 或者,如果您想连接多个 TypeList
并将其转换为 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>>;
如何定义一个class MultiInherit<MyTuple<X1,X2,...>>
继承自X1,X2,...
?
我想传递 MyTuple<X1,X2,...>
来组成一个新的对象类型。
template <class... Xs> class MyTuple{};
template <class MyTupleXs> class MultiInherit : public All_Xs_in_MyTupleXs { //??
};
这是它的用法和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(){
}
尝试 1
下面是最接近我想要的。
如果我得到原始类型(例如 B,C
)作为模板参数而不是 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;
}
};
参考:
这不解决。我想传递一个封装类型 MyTuple<B,C>
,而不是 B,C
.
尝试 2
我想在 MyTuple
中添加一个新的可变类型定义 MyXs
:-
template <class... Xs> class MyTuple{
public: using MyXs=Xs...;
};
template <class MyTupleXs> class MultiInherit : public MyTupleXs::MyXs {
};
然而,在我看来,该语言没有这样的功能。
(我是可变参数模板的新手。)
简单回答
您必须 create a template specialization 个 MultiInherit
。让我们看看 MultiInherit
:
template<class... Xs>
class MultiInherit : public Xs... {
// Stuff
};
在这里,我们采用了一堆类型并继承了它们。但是我们可以使用模板特化来解包元组:
// Specialization on MyTuple
template<class... Xs>
class MultiInherit<MyTuple<Xs...>> : public Xs... {
// Stuff
};
这让您可以随心所欲。给定一个 MyTuple
,你有一个继承自所有成员的 MultiInherit
class。
更一般的情况
定义类型列表。如果您想做一些更一般的事情,基于表示类型列表的模板来做它们会很有用。我们可以定义一个模板来表示一个类型列表:
template<class...>
struct TypeList {};
连接类型列表。我们可以定义更多模板来连接类型列表。 ConcatLists
是一个接受两个类型列表的函数,returns 一个 TypeList
连接它们:
template<class... Xs, class... Ys>
TypeList<Xs..., Ys...> ConcatLists(TypeList<Xs...>, TypeList<Ys...>) {
return {};
}
我们可以使用它来定义一个自动执行此操作的 concat_t
:
template<class TypeListA, class TypeListB>
using concat_t = decltype(ConcatLists(TypeListA{}, TypeListB{}));
用MultiInherit
代替TypeList
。 我们还可以使用模板特化用一种类型代替另一种类型。
// 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;
这意味着您可以将 TypeList
替换为 MultiInherit
:
template<class ListOfTypes>
using MultiInheritFromTypeList = substitute_list_t<MultiInherit, ListOfTypes>;
用法示例。 如果要将 TypeList
转换为 MultiInherit
:
using T1 = TypeList<int, char, bool>;
// T2 is MultiInherit<int, char, bool>;
using T2 = MultiInheritFromTypeList<T1>;
concat 示例。 或者,如果您想连接多个 TypeList
并将其转换为 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>>;