определить класс `MultiInherit <MyTuple <X1, X2, ... >>` для наследования от `X1, X2, ...` - PullRequest
2 голосов
/ 15 апреля 2019

Как определить класс 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

Ниже приведен наиболее близкий к тому, что ятребуемый.
Если я получу raw-типы (например, 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;   
    }
};  

Ссылка: Вариативные шаблоны и множественное наследование в c ++ 11
Это не решает проблему.Я хочу передать инкапсулированный тип MyTuple<B,C>, а не B,C.

Попытка 2

Я думал о добавлении нового variadic typedef MyXs в MyTuple: -

template <class... Xs> class MyTuple{
   public: using MyXs=Xs...;    
};
template <class MyTupleXs> class MultiInherit : public MyTupleXs::MyXs { 
};

Тем не менее, мне кажется, что в языке нет такой возможности.

(Я новичок в вариационных шаблонах.)

1 Ответ

5 голосов
/ 15 апреля 2019

Простой ответ

Вам необходимо создать шаблон специализации из 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, который наследуется от всех членов.

Более общий случай

Определение списка типов. Если вы хотите сделать что-то более общее, будет полезно сделать их на основе шаблонов, представляющих списки типов.Мы можем определить шаблон для представления списка типов:

template<class...>
struct TypeList {}; 

Объединение списков типов. Мы можем определить больше шаблонов для объединения списков типов.ConcatLists - это функция, которая принимает два списка типов и возвращает 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 s и преобразовать его в 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>>;
...