Я пытаюсь реализовать безопасную версию std :: shared_ptr, называемую "safe_ptr", которая гарантирует "ненулевое значение".
EDIT: Вопрос удален. Смотрите редактировать, если интересно. Отправка окончательного решения всем заинтересованным:
Этот код теперь размещен на код Google .
#pragma once
#include
#include
#include
template
class safe_ptr
{
template friend class safe_ptr;
public:
typedef T element_type;
safe_ptr() : impl_(std::make_shared()){}
safe_ptr(const safe_ptr& other) : impl_(other.impl_){}
template
safe_ptr(const safe_ptr& other, typename std::enable_if::value, void*>::type = 0) : impl_(other.impl_){}
template
safe_ptr(const U& impl, typename std::enable_if::type, T*>::value, void>::type* = 0)
: impl_(std::make_shared(impl)) {}
template
safe_ptr(const U& impl, D dtor, typename std::enable_if::type, T*>::value, void>::type* = 0)
: impl_(new U(impl), dtor) {}
template
safe_ptr(U&& impl, typename std::enable_if::type, T*>::value, void>::type* = 0)
: impl_(std::make_shared(std::forward(impl))) {}
template
safe_ptr(U&& impl, D dtor, typename std::enable_if::type, T*>::value, void>::type* = 0)
: impl_(new U(std::forward(impl)), dtor) {}
template
explicit safe_ptr(const std::shared_ptr& impl, typename std::enable_if::value, void*>::type = 0) : impl_(impl)
{
if(!impl_)
throw std::invalid_argument("impl");
}
template
explicit safe_ptr(std::shared_ptr&& impl, typename std::enable_if::value, void*>::type = 0) : impl_(std::move(impl))
{
if(!impl_)
throw std::invalid_argument("impl");
}
template
explicit safe_ptr(U* impl, typename std::enable_if::value, void*>::type = 0) : impl_(impl)
{
if(!impl_)
throw std::invalid_argument("impl");
}
template
explicit safe_ptr(U* impl, D dtor, typename std::enable_if::value, void*>::type = 0) : impl_(impl, dtor)
{
if(!impl_)
throw std::invalid_argument("impl");
}
template
typename std::enable_if::value, safe_ptr&>::type
operator=(const safe_ptr& other)
{
safe_ptr temp(other);
temp.swap(*this);
return *this;
}
template
typename std::enable_if::type, T*>::value, safe_ptr&>::type
operator=(U&& impl)
{
safe_ptr temp(std::forward(impl));
temp.swap(*this);
return *this;
}
T& operator*() const { return *impl_.get();}
T* operator->() const { return impl_.get();}
T* get() const { return impl_.get();}
bool unique() const { return impl_.unique();}
long use_count() const { return impl_.use_count();}
void swap(safe_ptr& other) { impl_.swap(other.impl_); }
operator std::shared_ptr() const { return impl_;}
template
bool owner_before(const safe_ptr& ptr){ return impl_.owner_before(ptr.impl_); }
template
bool owner_before(const std::shared_ptr& ptr){ return impl_.owner_before(ptr); }
template
D* get_deleter(safe_ptr const& ptr) { return impl_.get_deleter(); }
private:
std::shared_ptr impl_;
};
template
bool operator==(const safe_ptr& a, const safe_ptr& b)
{
return a.get() == b.get();
}
template
bool operator!=(const safe_ptr& a, const safe_ptr& b)
{
return a.get() != b.get();
}
template
bool operator<(const safe_ptr& a, const safe_ptr& b)
{
return a.get() < b.get();
}
template
bool operator>(const safe_ptr& a, const safe_ptr& b)
{
return a.get() > b.get();
}
template
bool operator>=(const safe_ptr& a, const safe_ptr& b)
{
return a.get() >= b.get();
}
template
bool operator<=(const safe_ptr& a, const safe_ptr& b)
{
return a.get() <= b.get();
}
template
std::basic_ostream& operator<<(std::basic_ostream& out, const safe_ptr& p)
{
return out << p.get();
}
template
void swap(safe_ptr& a, safe_ptr& b)
{
a.swap(b);
}
template
T* get_pointer(safe_ptr const& p)
{
return p.get();
}
template
safe_ptr static_pointer_cast(const safe_ptr& p)
{
return safe_ptr(std::static_pointer_cast(std::shared_ptr(p)));
}
template
safe_ptr const_pointer_cast(const safe_ptr& p)
{
return safe_ptr(std::const_pointer_cast(std::shared_ptr(p)));
}
template
safe_ptr dynamic_pointer_cast(const safe_ptr& p)
{
auto temp = std::dynamic_pointer_cast(std::shared_ptr(p));
if(!temp)
throw std::bad_cast();
return safe_ptr(temp);
}
template
safe_ptr make_safe()
{
return safe_ptr();
}
template
safe_ptr make_safe(P0&& p0)
{
return safe_ptr(std::make_shared(std::forward(p0)));
}
template
safe_ptr make_safe(P0&& p0, P1&& p1)
{
return safe_ptr(std::make_shared(std::forward(p0), std::forward(p1)));
}
template
safe_ptr make_safe(P0&& p0, P1&& p1, P2&& p2)
{
return safe_ptr(std::make_shared(std::forward(p0), std::forward(p1), std::forward(p2)));
}
template
safe_ptr make_safe(P0&& p0, P1&& p1, P2&& p2, P3&& p3)
{
return safe_ptr(std::make_shared(std::forward(p0), std::forward(p1), std::forward(p2), std::forward(p3)));
}
template
safe_ptr make_safe(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&&)
{
return safe_ptr(std::make_shared(std::forward(p0), std::forward(p1), std::forward(p2), std::forward(p3), std::forward(p4)));
}