【问题标题】:Copying vector<shared_pt<T>> to vector<shared_ptr<const T>> (different cases) C++将 vector<shared_pt<T>> 复制到 vector<shared_ptr<const T>> (不同情况)C++
【发布时间】:2016-09-01 07:07:53
【问题描述】:

我有一个:

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;
};

我觉得奇怪的是,当我使用复制构造函数时它不起作用,因为它无法计算从非常量到常量的转换?

xxxx.cpp:672:56: error: no matching constructor for initialization of 'std::vector<std::shared_ptr<const int> >'

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

【问题讨论】:

  • 如果它只是从非常量到常量的转换(即intconst int)就好了。然而,这不是这里发生的事情,它是从一种类型的对象到完全不同类型的对象的转换。并且复制构造函数仅将其自己的类型作为参数,而不是不同的类型。
  • 好吧,这是有道理的,但这样的事情不会起作用吗? int a = 1; const int b = a?所以我的问题是为什么这个分配有效,为什么不能使用复制构造函数来完成?我真的很好奇是什么阻止了它这样做?我认为这不是出于优化原因...
  • @user18490 const std::vector&lt;T&gt;std::vector&lt;const T&gt; 不同。因此与intconst int 的类比不成立。

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


【解决方案1】:

如果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;
};

【讨论】:

  • 请注意,container_cast 实现强制复制并且从不移动,在实际代码中使用它之前需要进行改进。 ;-]
【解决方案2】:

起初用不同类型实例化的类模板是完全不同的类型。那么std::shared_ptr&lt;int&gt;std::shared_ptr&lt;const int&gt;是完全不同的类型,std::vector&lt;std::shared_ptr&lt;int&gt;&gt;std::vector&lt;std::shared_ptr&lt;const int&gt;&gt;也是不同的类型,不能相互转换。

根据std::vectorconstructors,复制构造函数(第5个)接受一个与参数类型相同的std::vector。这意味着对于std::vector&lt;std::shared_ptr&lt;const int&gt;&gt;,它不能接受std::vector&lt;std::shared_ptr&lt;int&gt;&gt;,它不能隐式转换为std::vector&lt;std::shared_ptr&lt;const int&gt;&gt;

另一方面,采用迭代器范围(第4个)的构造函数是函数模板,迭代器的类型是模板参数,它不一定是指向相同类型的迭代器。如果该类型可用于构造向量,则允许为指向其他类型的迭代器。 std::shared_ptr&lt;int&gt;可以用来构造std::shared_ptr&lt;const int&gt;,就可以了。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-20
    • 2017-07-18
    • 1970-01-01
    • 1970-01-01
    • 2018-02-02
    • 2020-10-17
    • 1970-01-01
    相关资源
    最近更新 更多