不可复制的对象、映射和shared_ptr:复制构造函数中出错

Uncopyable object, map and shared_ptr : error in the copy constructor

本文关键字:ptr 复制 构造函数 出错 shared 可复制 对象 映射      更新时间:2023-10-16

我在构造不可复制的对象时遇到问题。让我们考虑以下示例:

class Uncopyable{
protected:
Uncopyable(){};
~Uncopyable(){};
private:
Uncopyable(const Uncopyable&);
Uncopyable& operator=(const Uncopyable&);
};

class Base { };
class Derived : public Base { };
class A : private Uncopyable {
public:
A(std::map<std::string, std::shared_ptr<Base>> & inMap);
private:
A(const A&);
A& operator=(const A&);
};
int main() {
std::map<std::string, std::shared_ptr<Derived>> lMap;
std::shared_ptr<A> oA(std::make_shared<A>(lMap));
}

如果我假设我的对象A是不可复制的,那么它就不起作用。作为一个指针,我希望我的对象a理解Derived是一个Base,但我得到了以下消息:

error C2664: 'A::A(const A &)' : cannot convert argument 1 from 'std::map<std::string,std::shared_ptr<Derived>,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>' to 'std::map<std::string,std::shared_ptr<Base>,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>> &'
1>          with
1>          [
1>              _Kty=std::string
1>  ,            _Ty=std::shared_ptr<Derived>
1>          ]
1>          and
1>          [
1>              _Kty=std::string
1>  ,            _Ty=std::shared_ptr<Base>
1>          ]

谢谢。

错误与A的不可压缩性无关,实际上不在复制构造函数中,而是在map构造函数中。该错误与A'构造函数采用有关

std::map<std::string, std::shared_ptr<Base>> &

而你正在通过一个:

std::map<std::string, std::shared_ptr<Derived>>

作为类型T的左值引用的自变量只能由类型T或从T派生的类型(或具有operator T&的类型)的左值来满足。但是std::map<std::string, std::shared_ptr<Derived>>实际上并没有从std::map<std::string, std::shared_ptr<Base>>继承——这两种类型也根本没有关联——std::map没有跨类型构造函数。

换句话说,仅仅因为DB并不意味着map<X, D>map<X, B>。以这种方式,在C++类型系统中不存在类型的协方差。某些类型至少允许您从Class<D>(例如std::shared_ptr)构造Class<B>,但标准容器(例如vectormap…)则不然

您必须更改lMap以保持std::shared_ptr<Base>秒,才能使其工作。它可以在内部容纳std::shared_ptr<Derived>s,但map类型必须匹配。


旁注,在C++11中,您不需要Uncopyable。您可以简单地显式delete这些操作:

A(A const& ) = delete;
A& operator=(A const& ) = delete;