Я реализую пользовательский вектор указателей my_ptr_vector
.Сделать контейнер covariant
У меня есть класс Base
и Derived
, получающий Base
.
У меня есть метод, который должен действовать (по ссылке const!) На обоих my_ptr_vector<Base>
и my_ptr_vector<Derived>
. Конечно, он только ссылается на методы элементов из класса Base
.
Однако компилятор жалуется, что он не имеет способа преобразования my_ptr_vector<Derived>
в my_ptr_vector<Base>
.
Minimal пример воспроизведения проблемы:
#include <vector>
#include <memory>
class Base {};
class Derived : public Base {};
template<typename Element>
class my_ptr_vector : public std::vector< std::unique_ptr<Element> > {};
void funct(const my_ptr_vector<Base>& vect) {}
int main()
{
my_ptr_vector<Derived> vect;
funct(vect);
}
ошибка:
no suitable user-defined conversion from "my_ptr_vector<Derived>" to "const my_ptr_vector<Base>" exists
Я нашел here, что я мог бы сделать его работу, если я предоставил оператор конструктора и назначения из my_ptr_vector<U>
, с U
общий, так что U*
может быть преобразован в T*
.
Действительно, если в примере изменить класс к этому, он работает
template<typename Element>
class my_ptr_vector : public std::vector< std::shared_ptr<Element> > {
public:
my_ptr_vector() {}
///copy constructor from vector of pointers to generic U
template<typename DerivedElement>
my_ptr_vector(const my_ptr_vector<DerivedElement>& oth)
{
printf("Oh, noes!"); //we don't want this method executed!
resize(oth.size());
for (std::shared_ptr<Element> ptr : oth)
{
push_back(ptr);
}
}
};
Однако ли выполнить print
заявление в конструкторе -это не просто намек, что он не должен беспокоиться ; он фактически выполняет преобразование!
Есть ли способ избежать этого?
Другим возможным решением является, конечно, сделать func
шаблонный:
template<typename T>
void funct(const my_ptr_vector<T>& vect) {}
Однако, в этом случае я потеряю информацию, что внутри func
, элементы vect
всегда являются типа Base
.
Проще, если вы укажете нам код ([mcve]). Моя первая мысль заключается в использовании 'my_ptr_vector ', что является обычным способом обработки векторов классов, некоторые из которых могут быть получены. –
Возможно, вы ищете старый добрый [std :: vector] (http://en.cppreference.com/w/cpp/container/vector) из [std :: unique_ptr] (http: //en.cppreference. com/w/cpp/memory/unique_ptr) или [std :: shared_ptr] (http://en.cppreference.com/w/cpp/memory/shared_ptr)? –
@ ТопологическийСорт вы правы, сделано :) –