Наследовать от классов, передаваемых конструктору в качестве параметров шаблона, наследовать от них - PullRequest
1 голос
/ 29 октября 2019

Я хочу получить что-то подобное:

template<class... Args>
class MyClass : public Args
{
    MyClass<class... Args>(/*some parameters*/)
    { }
}

// ana then:
MyClass<Base1, Base2, Base3>(/*some arguments*/)

Что я хочу dynamic_cast до Base1 или т. Д. И использовать его методы.

Я знаю, что этокод не будет работать, но есть ли у вас идеи, как это сделать?

Ответы [ 4 ]

2 голосов
/ 29 октября 2019

Это прекрасно работает:

struct Base1
{};
struct Base2
{};
struct Base3
{};

template<class... Args>
struct MyClass : public Args...
{};

MyClass<Base1, Base2, Base3> mc;

Нет необходимости в <> в вашем конструкторе, вы пропускаете "..." после public Args и пропускаете ";"в конце вашего определения класса.

1 голос
/ 29 октября 2019

Сначала вы используете неверный синтаксис. При использовании шаблонов с переменными параметрами вам необходимо «распаковать» их (правильный термин: «расширить пакет параметров») при их использовании:

template<typename... Args>
class MyClass : public Args ...
//                          ^^^
{ };

В конструкторе вы можете полностью пропустить параметры шаблона, но если вы укажете их, вам нужно снова «распаковать» их:

MyClass<Args ...>(/*some parameters*/);
//     ^^^^^^^^^^   optional

После того, как класс определен, вы можете указать аргументы шаблона так же, как с классическими шаблонами, только числоможет отличаться:

MyClass<Base1> c1;
MyClass<Base1, Base2> c2;
MyClass<Base1, Base2, Base3> c3;

Начиная с C ++ 17 и с соответствующим конструктором, вы даже можете позволить выводить аргументы шаблона класса:

template<typename... Args>
class MyClass : public Args ...
{
public:
    MyClass(Args const&... args)
        : Args(args)... // call base class copy constructors!
                        // (note the unpacking again)
    { }
    MyClass(Args&&... args)
        : Args(std::forward(args))... // call base class move constructors!
                                      // (note the unpacking again)
    { }
};

MyClass c0;
MyClass c1(Base1());
MyClass C2(Base1(), Base2());

std::cout << std::is_same_v<decltype(c0), MyClass<>> << std::endl;
std::cout << std::is_same_v<decltype(c1), MyClass<Base1>> << std::endl;
std::cout << std::is_same_v<decltype(c2), MyClass<Base1, Base2>> << std::endl;

Обратите внимание, что наследование здесь - красная сельдь, который работает без также. См. Вывод аргумента шаблона класса .

1 голос
/ 29 октября 2019

Я знаю, что этот код не будет работать, но есть ли у вас какие-либо идеи, как это сделать?

Чтобы это работало, вам нужно

(1) добавить многоточие (...), наследующее Args...

class MyClass : public Args...
// ........................^^^

(2), сделать MyClass a struct или сделать public конструктором

(3) удалить<class... Args> часть, определяющая конструктор (он неявный)

(4), добавьте несколько следующим образом

   Args const & ... as

для аргументов конструктора

(5) добавьте точку с запятойкласс или структура

Теперь работает следующий код

struct Base1 {};
struct Base2 {};
struct Base3 {};

template<class... Args>
struct MyClass : public Args...
 {
   MyClass (Args const & ...)
    { }
 };

int main()
 {
   MyClass<Base1, Base2, Base3>(Base1{}, Base2{}, Base3{});

   MyClass(Base1{}, Base2{}, Base3{});  // C++17 only
 }

Обратите внимание на последнюю строку в main()

MyClass(Base1{}, Base2{}, Base3{});  // C++17 only

Работает только из C ++ 17, потому что используетновый C ++ 17: руководства по выводам.

В вашем случае существуют неявные руководства по выводам, которые позволяют выводить типы шаблонов класса из типов аргумента, передаваемого конструктору.

Другим примером использования (более полезным?) Может быть

MyClass  mc{ Base1{}, Base2{}, Base3{} };
0 голосов
/ 29 октября 2019

Позвольте мне показать вам несколько рабочих примеров, как вы просили:

#include<iostream>

class B1 {
private:
int *m;
public:
B1() { m = new int;}
~B1() { delete m;}
void SetM(int a) { *m = a;}
int GetM() { return *m;}
};

class B2 {
private:
std::string str;
public:
B2() { str = "";}
~B2() {}
void SetStr(std::string a) { str = a;}
std::string GetStr() { return str;}
};

class B3 {
private:
float f;
public:
B3() { f = 0.0 ;}
~B3() {}
void SetF(float a) { f = a;}
float GetF() { return f;}
};

template<class... Args>
class MyClass : public Args... {
};

int main () {
MyClass<B1,B2,B3> l;
l.SetM(1);
if (auto a = dynamic_cast<B1*>(&l)) {
    std::cout<<" " << a->GetM() <<"\n";
} else {
    std::cout<<"ERROR:\n";
}

}

Надеюсь, это поможет, спасибо,

Раджкумар

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...