使容器协变

Make container covariant

本文关键字:      更新时间:2023-10-16

我正在实现指针my_ptr_vector的自定义向量。

我有一个类Base和一个Derived派生Base

我有一个方法应该在my_ptr_vector<Base>my_ptr_vector<Derived>上起作用(通过const引用!)。当然,它只调用来自Base类的元素方法。

但是,编译器抱怨它没有办法将my_ptr_vector<Derived>转换成my_ptr_vector<Base>

重现问题的最小示例:

#include <vector>
#include <memory>
class Base {};
class Derived : public Base {};
template<typename Element>
class my_ptr_vector : public std::vector< std::unique_ptr< Element > > {};
void funct(const my_ptr_vector<Base>& vect) {}
int main()
{
    my_ptr_vector<Derived> vect;
    funct(vect);
}
错误:

no suitable user-defined conversion from "my_ptr_vector<Derived>" to "const my_ptr_vector<Base>" exists 

我在这里发现,如果我从my_ptr_vector<U>提供构造函数和赋值操作符,使用U泛型,这样U*可以转换为T*,我可以使它工作。

实际上,如果在这个例子中我将类更改为this,它就可以工作了

template<typename Element>
class my_ptr_vector : public std::vector< std::shared_ptr< Element > > {
public: 
    my_ptr_vector() {}
    ///copy constructor from vector of pointers to generic U
template<typename DerivedElement>
    my_ptr_vector(const my_ptr_vector<DerivedElement>& oth)
    {
        printf("Oh, noes!");  //we don't want this method executed!
        resize(oth.size());
        for (std::shared_ptr< Element > ptr : oth)
        {
            push_back(ptr);
        }
    }
};

然而,它确实在构造函数中执行print语句——这不仅仅是暗示它不应该担心;它实际上是在执行转换!

有办法避免这种情况吗?

另一个可能的解决方案当然是使func模板化:

template<typename T>
    void funct(const my_ptr_vector<T>& vect) {}

但是,这样我就丢失了在func内部,vect的元素总是Base类型的信息。

这似乎是您想要的。代码的第二部分,复制函数,不需要修改。

我不认为你可以摆脱需要转换到std::unique_ptr。它想要这样,即使它推送的是Base*

#include <vector>
#include <memory>
class Base {};
class Derived : public Base {};
template<typename Element>
class my_ptr_vector : public std::vector< std::unique_ptr< Element > > {};
void funct(const my_ptr_vector<Base>& vect) {}
int main()
{
  my_ptr_vector<Base> vect;
  vect.push_back(std::unique_ptr<Base>(new Derived)); 
  funct(vect);
}
相关文章:
  • 没有找到相关文章