Альтернативный подход к методу виртуального шаблона

#c #oop #templates #polymorphism #virtual

Вопрос:

я пытаюсь решить эту проблему в течение некоторого времени и надеюсь найти здесь некоторую помощь. У меня есть базовый класс, и внутри базового класса мне нужен метод шаблона. Но этот метод не может быть виртуальным (что я знаю), поэтому я не могу переопределить его в дочернем классе, но есть ли какая-либо альтернатива или обходной путь? Какой-то шаблон дизайна? Спасибо

 #include <iostream>
#include <vector>
#include <map>

class ABase {
public:
    ABase() :
        id(s_id  )
    {}

    size_t static   s_id;
    size_t          id;
};

size_t ABase::s_id(0);

class A1 : public ABase {
public:
};

class A2 : public ABase {
public:
};

class BBase {
public:
};

class B1 : public BBase {
public:
};

class B2 : public BBase {
public:
};

class ComboBase {
public:
    //  this cannot be virtual :(
    //  so i cannot store b in bs in the child class
    /* virtual */ template<typename T>
    void addB(T b) {
    }
};

template<class T, class T2>
class Combo : public ComboBase {
public:
    //  override of template method is not possible
    /*
    template<typename T>
    void addB(T b) override {
        bs.push_back(b);
    }
    */

    size_t                              id;
    std::shared_ptr<T>                  a;
    std::vector<std::shared_ptr<T2>>    bs;
};

int main() {
    std::map<size_t, std::shared_ptr<ComboBase>> combos;
    auto combo1 = std::make_shared<Combo<A1, B1>>();
    auto combo2 = std::make_shared<Combo<A2, B2>>();
    combos[combo1->id] = combo1;
    combos[combo2->id] = combo2;

    //  here is the problem... later i the code
    //  i would like to add Bs to the existing combo but i cannot use
    //  virtual templates
    auto b1 = std::make_shared<B1>();
    auto b2 = std::make_shared<B2>();

    auto it1 = combos.find(0);
    if (it1 != combos.end()) {
        it1->second->addB(b1);
        it1->second->addB(b2);
    }

    auto it2 = combos.find(0);
    if (it2 != combos.end()) {
        it2->second->addB(b1);
        it2->second->addB(b2);
    }
}
 

Комментарии:

1. @KonradRudolph ой, мой плохой — не прокрутил достаточно далеко вниз.

2. template<typename T> void addB(T b) Шаблон функции, подобный этому, должен быть способен принимать любые аргументы. Что должно произойти, если я позвоню addB(42) или addB(new int[1000]) или addB(std::string("good bye, cruel world")) ?

3. Обычно я бы сказал CRTP , но то, как вы его используете, кажется, не вариант.