将 vector<shared_ptr<T>> 复制到 vector<shared_ptr<const T>> 中(不同情况)C++

7

我有一个:

std::vector<std::shared_ptr<T>>

Which I would like to copy to a

std::vector<std::shared_ptr<const T>>

现在我注意到,如果我这样做:
class A
{
public:
    A(const std::vector<std::shared_ptr<int>>& list) : internalList(list.begin(), list.end()) {}
    std::vector<std::shared_ptr<const int>> internalList;
};

代码可以通过编译 (使用clang++且标准为c++14),但是如果我执行以下操作:

class A
{
public:
    A(const std::vector<std::shared_ptr<int>>& list) : internalList(list) {}
    std::vector<std::shared_ptr<const int>> internalList;
};

我发现使用拷贝构造函数时会出现奇怪的问题,因为它无法确定从非 const 转换到 const 的转换方式。
xxxx.cpp:672:56: error: no matching constructor for initialization of 'std::vector<std::shared_ptr<const int> >'

请有人解释一下为什么,以及我使用构造函数中的迭代器的方法是否是最佳解决方案?


1
如果只是从非const转换为const(即从intconst int),那就没问题了。但这里发生的不是这种情况,而是从一个完全不同类型的对象转换为另一个对象。而且复制构造函数只接受自己类型的参数,而不是不同类型的参数。 - Some programmer dude
好的,这很有道理,但是像这样行不行? int a = 1; const int b = a?所以我的问题是为什么这个赋值可以工作,而使用复制构造函数却不能呢?我真的很好奇它为什么不能这样做?我猜想这不是出于优化的原因... - user18490
1
@user18490 const std::vector<T> 不同于 std::vector<const T>。因此,与 intconst int 的类比不成立。 - R Sahu
2个回答

3

如果std::vector提供了转换构造函数,那么您的代码可以正常工作:

template<class T, class A = std::allocator<T>>
class vector {
public:
    template<class T1, class A1>
    explicit vector(const vector<T1, A1>& other)
        : vector(other.begin(), other.end())
    {}

    ...
};

然而,在每个标准库容器中都拥有这样一个构造函数并没有太多价值,因为通过引入一个更通用的container_cast实用程序(例如,参见这个答案),几乎可以实现相同的效果。那么你就可以这样写:

class A
{
public:
    A(const std::vector<std::shared_ptr<int>>& list) : internalList(container_cast(list)) {}
    std::vector<std::shared_ptr<const int>> internalList;
};

请注意,container_cast 的实现强制执行复制而不是移动,在将其用于实际代码之前需要进行改进。;-] - ildjarn

2
最初,使用不同类型实例化的类模板完全是不同的类型。然后,std::shared_ptr和std::shared_ptr是完全不同的类型,std::vector>和std::vector>也是不同的类型,并且不能相互转换。
根据std::vector的构造函数(第5个),复制构造函数接受与其参数相同类型的std::vector。这意味着对于std::vector>,它不能接受std::vector>,因为它不能隐式地转换为std::vector>。
另一方面,接受迭代器范围的构造函数(第四个构造函数)是一个函数模板,迭代器的类型是模板参数,不必指向相同类型的迭代器。如果这个类型可以用来构造向量,则允许使用指向其他类型的迭代器。例如,std::shared_ptr<int> 可以用来构造 std::shared_ptr<const int>,那么这是可以的。
请注意,std::shared_ptr 有复制/移动构造函数模板,可以将具有不同元素类型的 std::shared_ptr 作为其参数。(而 std::vector 没有此功能。)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接