patterncppMinor
A clone_ptr<T> that does not require T to have a clone method
Viewed 0 times
methodclone_ptrthatrequiredoesnothaveclone
Problem
Here is my clone pointer template:
It is primarily intended to preserve polymorphism, esp. when stored in a container. It "forwards"
Have I missed/forgotten anything?
#include
#include
#include
template
struct clone_ptr
{
clone_ptr() : ptr(nullptr), cloner(nullptr) {}
clone_ptr(clone_ptr&& other) noexcept
: clone_ptr()
{
swap( other );
}
clone_ptr(const clone_ptr& other)
{
ptr = other.cloner(other.ptr);
cloner = other.cloner;
}
void swap( clone_ptr& other ) noexcept
{
using std::swap;
swap( ptr, other.ptr );
swap( cloner, other.cloner );
}
clone_ptr& operator=( const clone_ptr& other )
{
clear();
ptr = other.cloner(other.ptr);
cloner = other.cloner;
return *this;
}
clone_ptr& operator=( clone_ptr&& other )
{
clear();
swap(other);
return *this;
}
T* operator->() { return ptr; }
const T* operator->() const { return ptr; }
T& operator*() { return *ptr; }
const T& operator*() const { return *ptr; }
operator bool() const { return ptr; }
bool operator"; return os ; }
template
void make( Ts&& ...ts )
{
clear();
ptr = new T2( std::forward(ts)... );
cloner = [](T* p) -> T* { return new T2( * (T2*) p ); };
}
void clear() { delete ptr; ptr=nullptr; cloner=nullptr; }
~clone_ptr() { clear(); }
private:
T* ptr;
std::function cloner;
};
template
clone_ptr make_cloned( Ts&& ...ts )
{
clone_ptr p;
p.template make( std::forward(ts)... );
return p;
}
template
std::ostream& operator& p) { return p.output(os); }It is primarily intended to preserve polymorphism, esp. when stored in a container. It "forwards"
operator< and operator== so containers can be sorted etc. based on the contained object.Have I missed/forgotten anything?
Solution
Prefer to use Copy and Swap Idiom
Or
No need to clear on move assignment
Easier to write as:
Personally I don't see the point in havin output() and operator<<
I would just combine them into
clone_ptr& operator=( const clone_ptr& other )
{
clear();
ptr = other.cloner(other.ptr);
cloner = other.cloner;
return *this;
}Or
clone_ptr& operator=(clone_ptr copy)
{
copy.swap(*this);
return *this;
}No need to clear on move assignment
clone_ptr& operator=( clone_ptr&& other )
{
// clear(); No need to do that.
The destructor of `other` will do that at some point.
swap(other);
return *this;
}Easier to write as:
clone_ptr& operator=(clone_ptr copy)
{
copy.swap(*this);
return *this;
}Personally I don't see the point in havin output() and operator<<
I would just combine them into
operator<< and make it a friend (also declare it in the class).Code Snippets
clone_ptr& operator=( const clone_ptr& other )
{
clear();
ptr = other.cloner(other.ptr);
cloner = other.cloner;
return *this;
}clone_ptr& operator=(clone_ptr copy)
{
copy.swap(*this);
return *this;
}clone_ptr& operator=( clone_ptr&& other )
{
// clear(); No need to do that.
The destructor of `other` will do that at some point.
swap(other);
return *this;
}clone_ptr& operator=(clone_ptr copy)
{
copy.swap(*this);
return *this;
}Context
StackExchange Code Review Q#92593, answer score: 3
Revisions (0)
No revisions yet.