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

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

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

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 是不可复制的,它不是 work.As 指针,我希望我的对象 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> 构建 Class<B>(例如 std::shared_ptr),但标准容器并非如此(例如 vectormap, ...)

您必须将 lMap 更改为保持 std::shared_ptr<Base>s 才能使其正常工作。它可以在内部保存 std::shared_ptr<Derived>s - 但 map 类型必须匹配。


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

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