Класс с элементом данных, который может быть одного из двух типов - PullRequest
1 голос
/ 31 марта 2020

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

class MyClass {
  public:
    MyClass(const std::string& d1, const std::string& d2, const std::vector<AorB>& d3) : data1(d1), data2(d2), data3(d3) {}

    std::string getData1();
    std::string getData2();
    std::vector<AorB> getData3();

  private:
    std::string data1;
    std::string data2;
    std::vector<AorB> data3;
}

int main() {
  MyClass myClassA("d1", "d2", std::vector<A>());
  MyClass myClassB("d1", "d2", std::vector<B>());

  A myA = myClassA.getData3();
  B myB = myClassB.getData3();
}

Этот рабочий процесс "почти" работает при использовании вариантов Boost или Boost любого, но я стараюсь избегать вызова boost :: get на результат getData3, чтобы получить фактический тип. Другими словами, я не хочу, чтобы потребитель MyClass знал, хранится ли A или B в data3. Я просто хочу, чтобы они могли вызывать getData3 () любого типа, который был передан при создании.

Я думаю, что это возможно с помощью шаблонов со специализацией / рекурсивным наследованием шаблонов, но я не могу понять, как чтобы это работало. Может быть, это будет выглядеть примерно так?

class MyClass {
  public:
    template <typename AorB>
    MyClass(const std::string& d1, const std::string& d2, const std::vector<AorB>& d3) : data1(d1), data2(d2), data3(d3) {}

    std::string getData1();
    std::string getData2();

    template <typename AorB>
    std::vector<AorB> getData3();

  private:
    std::string data1;
    std::string data2;

    template <typename AorB>
    std::vector<AorB> data3;
  }

  int main() {
    MyClass myClassA<A>("d1", "d2", std::vector<A>());
    MyClass myClassB<B>("d1", "d2", std::vector<B>());

    A myA = myClassA.getData3();
    B myB = myClassB.getData3();
  }

Однако это не сработает, потому что у нас не может быть нестандартных c членов класса шаблона.

Ответы [ 2 ]

3 голосов
/ 31 марта 2020

Чтобы сделать то, что вы пытаетесь, вам нужно применить шаблон к MyClass в целом, например:

template <typename AorB>
class MyClass {
  public:
    MyClass(const std::string& d1, const std::string& d2, const std::vector<AorB>& d3) : data1(d1), data2(d2), data3(d3) {}

    std::string getData1();
    std::string getData2();
    std::vector<AorB> getData3();

  private:
    std::string data1;
    std::string data2;
    std::vector<AorB> data3;
};

int main() {
  MyClass<A> myClassA("d1", "d2", std::vector<A>());
  MyClass<B> myClassB("d1", "d2", std::vector<B>());

  A myA = myClassA.getData3();
  B myB = myClassB.getData3();
}
0 голосов
/ 31 марта 2020

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

union AorB
   {
         A;
         B;
   };

Затем используйте в указанной выше программе

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