【问题标题】:static polymorphism and template Containers静态多态和模板容器
【发布时间】:2020-02-19 12:49:36
【问题描述】:

我正在尝试使用静态多态性和模板来创建一个可以容纳更多一种类型的容器,据我所知模板无法完成,但我希望我错了有一种方法。 我有以下课程:

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);

【问题讨论】:

  • base 和 base 是不同的、不相关的类型。
  • 您可以在您的类型上创建一些类型擦除或 std:: 变体的容器。
  • fwiw 容器可以容纳不同类型的对象,寻找“类型擦除”,std::any 或只是std::vector&lt;baseClass*&gt;
  • 容器内所有事物的静态类型必须相同。这意味着静态多态与它不兼容。但是,元素可以有不同的 dynamic 类型(当然,这是运行时多态性)。

标签: c++ templates c++17 rtti static-polymorphism


【解决方案1】:

经过一些测试和挖掘,答案是没有办法做到这一点。 但是你可以使用 std::any 像@以前已知的_463035818 建议 将 std::vector 声明为:

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

代替

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

并使用 boost demangle 函数获取类型 -

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';
     }
   }

或者不使用 demangle 名称并使用字符串比较,您可以使用类的 type() 函数 any 并且比较类型 ID,如下所示:

    if(e.type()==typeid(base<derived1>*))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-21
    • 1970-01-01
    • 2013-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-28
    • 1970-01-01
    相关资源
    最近更新 更多