复制矢量<shared_pt <t>&gt; to vector <shared_ptr <const t =“”>&gt; (不同的情况)C ++

时间:2016-09-01 07:07:53

标签: c++ c++11 c++14

我有一个:

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

我想将其复制到

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 ++ std == 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> >'

有人可以解释为什么请,如果我这样做(在构造函数中使用迭代器)是最好的解决方案吗?

2 个答案:

答案 0 :(得分: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实用程序可以实现几乎相同的效果(例如,参见this answer)。然后你可以写:

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

答案 1 :(得分:2)

首先,使用不同类型实例化的类模板完全是完全不同的类型。然后std::shared_ptr<int>std::shared_ptr<const int>是完全不同的类型,std::vector<std::shared_ptr<int>>std::vector<std::shared_ptr<const int>>也是不同的类型,并且无法相互转换。

根据std::vector的{​​{3}},复制构造函数(第5个)采用与其参数类型相同的std::vector。这意味着对于std::vector<std::shared_ptr<const int>>,它不能std::vector<std::shared_ptr<int>>,而是无法隐式转换为std::vector<std::shared_ptr<const int>>

另一方面,构造函数采用迭代器范围(第4个)是函数模板,迭代器的类型是模板参数,它不必是指向相同类型的迭代器。如果此类型可用于构造向量,则允许它指向其他类型的迭代器。 std::shared_ptr<int>可用于构建std::shared_ptr<const int>,然后就可以了。

请注意constructors具有复制/移动构造函数模板,这些模板可以将std::shared_ptr作为其参数使用不同的元素类型。 (虽然std::vector没有。)