Статический полиморфизм и шаблоны контейнеров - PullRequest
1 голос
/ 23 октября 2019

Я пытаюсь использовать статический полиморфизм и шаблон, чтобы создать контейнер, который может содержать больше одного типа, из того, что я знаю о шаблоне, это не может быть сделано, но я надеюсь, что я ошибаюсь иесть выход. У меня есть следующие классы:

template<class Derived>
class base
{
public:
    base(string);
    void clean()
    {
        cout << "I'm cleannig \n";
    }
    void process()
    {
        static_cast<Derived*>(this)->setup();
        static_cast<Derived*>(this)->run();
        static_cast<Derived*>(this)->cleanup();
    }
    string name;
};

template<class Derived>
base<Derived>::base(string y):name(y)
{
}


class derived : public  base<derived> 
{
    friend class base<derived>;
    void setup() {cout << "derived setup \n"; }
    void run() { cout << "derived run \n"; }
    void cleanup() { cout << "derived cleanup \n"; }

};


class derived1 : public base<derived1> 
{
    friend class base<derived1>;
    void setup() {cout << "derived1 setup \n"; }
    void run() { cout << "derived1 run \n"; }
    void cleanup() { cout << "derived1 cleanup \n"; }
};

, и я хочу создать контейнер, который может содержать их, я попробовал этот код -

template <class T>
class Y{
 public:
 std::vector<base<T>> m_vec;   

};


template <typename T>
class D:public Y<T>
{
    public:
    friend class Y<T>;
    void print()
    {
        for(auto& e: Y<T>::m_vec)
        {
            e.process();
        }
    } 
};


int main()
{ 
    base<derived>* b =  new base<derived>;
    base<derived1>* c =  new base<derived1>;

    D<derived> y;
    y.m_vec.push_back(b);
    y.m_vec.push_back(c);
    y.print();
}

, но он не работает, я пытался сделать это:

 y.m_vec.push_back(static_cast<base<derived>>(c));

и я получаю эту ошибку:

ошибка: не соответствует функция для вызова 'std :: vector, std :: allocator>> :: push_back(base * &) 'y.m_vec.push_back (b);

1 Ответ

0 голосов
/ 23 октября 2019

после некоторого тестирования и копания ответ - нет способа сделать это. но вы можете использовать std :: any like @ прежние известные__303035818, предложив объявить std :: vector как:

`std::vector<std::any> m_vec;`

вместо

std::vector<base<T>> m_vec;

и использовать повышениеРазобрать функцию, чтобы получить тип -

std::string name(boost::core::demangle(e.type().name()));

, а затем использовать какую-то фабричную функцию для any_cast для нужного вам типа

 if(!name.compare("base<derived1>*") )
 {
     try {
             auto* r = any_cast<base<derived1>*>(e);
             r->process();
         }
         catch(const std::bad_any_cast& e) {
             std::cout << e.what() << '\n';
         }
  }
  else
  {
     try {
         auto *r = any_cast<base<derived> *>(e);
         r->process();
     }
     catch(const std::bad_any_cast& e) {
         std::cout << e.what() << '\n';
     }
   }

или вместо использования имени деманглиста и использования строкисравните, вы можете использовать функцию type () класса any и сравнить с typeid следующим образом:

    if(e.type()==typeid(base<derived1>*))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...