Для этого можно создать новый тип clone_ptr
.
Ниже приведен элементарный пример clone_ptr
, который вызывает правильный конструктор копирования (и деструктор) производного объекта.Это делается здесь путем создания помощника «стирания типа» при создании clone_ptr
.
Другие реализации можно найти в Интернете.
#include <memory>
namespace clone_ptr_detail
{
template <class T>
class clone_ptr_helper_base
{
public:
virtual ~clone_ptr_helper_base() {}
virtual T* clone(const T* source) const = 0;
virtual void destroy(const T* p) const = 0;
};
template <class T, class U>
class clone_ptr_helper: public clone_ptr_helper_base<T>
{
public:
virtual T* clone(const T* source) const
{
return new U(static_cast<const U&>(*source));
}
virtual void destroy(const T* p) const
{
delete static_cast<const U*>(p);
}
};
}
template <class T>
class clone_ptr
{
T* ptr;
std::shared_ptr<clone_ptr_detail::clone_ptr_helper_base<T>> ptr_helper;
public:
template <class U>
explicit clone_ptr(U* p): ptr(p), ptr_helper(new clone_ptr_detail::clone_ptr_helper<T, U>()) {}
clone_ptr(const clone_ptr& other): ptr(other.ptr_helper->clone(other.ptr)), ptr_helper(other.ptr_helper) {}
clone_ptr& operator=(clone_ptr rhv)
{
swap(rhv);
return *this;
}
~clone_ptr()
{
ptr_helper->destroy(ptr);
}
T* get() const { /*error checking here*/ return ptr; }
T& operator* () const { return *get(); }
T* operator-> () const { return get(); }
void swap(clone_ptr& other)
{
std::swap(ptr, other.ptr);
ptr_helper.swap(other.ptr_helper);
}
};
См. Пример использования: http://ideone.com/LnWa3
(Но, возможно, вам на самом деле не нужно копировать ваших объектов, и вы могли бы скорее изучить возможности перемещениясемантика. Например, вы можете иметь vector<unique_ptr<T>>
, если вы не используете функции, которые копируют содержимое.)