Как передать экземпляр шаблона другому экземпляру другого шаблона? - PullRequest
3 голосов
/ 11 февраля 2020

У меня есть два шаблона классов, которые должны быть шаблонами ( C ++ ). Я просто упростил их код, чтобы показать суть проблемы. Как передать объект (obj1) из одного шаблона (MyClass1) в другой объект (obj2) из второго шаблона (MyClass2)? Я пробовал через параметр шаблона и конструктор, но у меня все еще есть ошибки компиляции. Как это сделать правильно? Что важно, я не знаю параметров шаблона, поэтому решение должно быть универсальным, а не для указанных параметров. Объект должен передаваться указателем или ссылкой, мне не нужна его копия.

template<int a, int b>
class MyClass1 {
  public:
    MyClass1() {
        // Do something...
    }

    int foo(int x) {
        return a * x + b;
    }
};
template<double m, double n>
class MyClass2 {
  public:
    MyClass2() {
        // Do something
    }

    double bar(int x) {
        // Do something with x using object of MyClass1 and then with m...
    }

    double zet(int x) {
        // Do something with x using object of MyClass1 and then with n...
    }
};
int main() {
    MyClass1<4, 3> obj1;
    MyClass2<3.14, 2.56> obj2; // <-- How to pass obj1 here???
    // Maybe that way?: MyClass2<3.14, 2.56, obj1> obj2;
    // Or that way?: MyClass2<3.14, 2.56> obj2(obj1);

    obj1.foo(12);
    obj2.bar(1.234);
    obj2.zet(5.678);
}

Я не уверен, относится ли это к этой проблеме, но я пишу Код C ++ для AVR в Atmel Studio 7 со стандартными настройками.

Ответы [ 2 ]

1 голос
/ 11 февраля 2020

Ваш код не компилируется с C ++ 11 из-за этого:

Параметр шаблона нетипичного типа должен иметь структурный тип, который является одним из следующих типов (необязательно, квалифицированным cv) квалификаторы игнорируются):

  • lvalue ссылочный тип (для объекта или для функции);
  • целочисленный тип;
  • тип указателя (для объекта или на функцию);
  • указатель на тип члена (на объект-член или на функцию-член);
  • тип перечисления;
  • std :: nullptr_t; (начиная с C ++ 11)
  • тип с плавающей точкой; (начиная с C ++ 20)

Что касается вашей основной проблемы, вы можете сделать что-то вроде этого:

template<int m, int n, typename Obj1Type>
class MyClass2 {
    Obj1Type obj1_;

public:
    MyClass2() {
        // Do something
    }

    MyClass2(Obj1Type const& obj1) {
        obj1_ = obj1;
    }

    // ...
};

И затем в main:

int main() {
    MyClass1<4, 3> obj1;
    MyClass2<3, 2, MyClass1<4, 3>> obj2(obj1);

    obj1.foo(12);
    obj2.bar(1);
    obj2.zet(5);
}

Проверьте это Live

ОБНОВЛЕНИЕ

Вы также можете использовать наследование и создать простой базовый класс для этого:

class BaseMyClass1 {};

template<int a, int b>
class MyClass1 : public BaseMyClass1 {
    // ...
};

template<int m, int n>
class MyClass2 {
    BaseMyClass1 obj1_;

public:
    MyClass2() {
        // Do something
    }

    template <typename Obj1Type>
    MyClass2(Obj1Type const& obj1) {
        obj1_ = obj1;
    }

    // ...
};

И затем в основном:

int main() {
    MyClass1<4, 3> obj1;
    MyClass2<3, 2> obj2(obj1);

    obj1.foo(12);
    obj2.bar(1);
    obj2.zet(5);
}

Это спасет вас от объявления шаблона в списке параметров шаблона. Тем не менее, это может быть не идеальным решением для вас, потому что оно вводит нарезку объектов.

Проверьте это live

0 голосов
/ 12 февраля 2020

Шаблонный класс принимает другой шаблонный класс в качестве параметра шаблона. Таким образом, вы можете передать typename T для Myclass2. Пример программы: вы можете попробовать что-то вроде этого:

#include <iostream>
using namespace std;

template<typename T1>
class Myclass1
{
    public:
    Myclass1(T1 x):m1_x(x)
    {
        cout << "Myclass1 C'tor" << m1_x << endl;
    }
    T1 m1_x;

    T1 get_x()
    {
        return m1_x;
    }
};

template < typename T1 >
class Myclass2
{
    public:
    Myclass2(T1 x): m_x(x)
    {
        cout << "My class 2 C'tor with value"  << m_x.get_x() << endl;
    }

    public:
    T1 m_x;
};


int main()
{
    Myclass1 <int > obj1(5000);

    Myclass2< Myclass1 <int> > obj2 ( obj1 );
    return 0;
}

...