Копирование вектора> в вектор> (разные случаи) C++
у меня:
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;
};
Я нахожу странным, что когда я использую конструктор копирования, он не работает, потому что он не может понять преобразование из non-const в const?
xxxx.cpp:672:56: error: no matching constructor for initialization of 'std::vector<std::shared_ptr<const int> >'
может кто-нибудь объяснить, почему, пожалуйста, и если так, как я это делаю (используя итератор в конструктор) является лучшим решением?
2 ответов
сначала шаблон класса, созданный с разными типами, является совершенно другим типом. Тогда std::shared_ptr<int>
и std::shared_ptr<const int>
совершенно разные типы, и std::vector<std::shared_ptr<int>>
и std::vector<std::shared_ptr<const int>>
также являются разными типами и не могут быть преобразованы друг в друга.
по словам конструкторы of std::vector
, конструктор копирования (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>
, тогда все в порядке.
отметим, что std:: shared_ptr есть копировать / переместить шаблоны конструкторов, которые могут принимать std::shared_ptr
С различным типом элемента в качестве аргумента. (А std::vector
нет.)
ваш код может работать, если 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;
};