Improved move-only deleters in C++03, now they can be caught as rvalues.

This commit is contained in:
Ion Gaztañaga
2014-08-29 10:28:09 +02:00
parent 364ee17476
commit 738e360f40
2 changed files with 146 additions and 173 deletions
+91 -80
View File
@@ -41,17 +41,37 @@ namespace boost{
namespace move_detail {
////////////////////////////////////////////
// deleter types
////////////////////////////////////////////
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <class T>
class is_noncopyable
{
typedef char true_t;
class false_t { char dummy[2]; };
template<class U> static false_t dispatch(...);
template<class U> static true_t dispatch(typename U::boost_move_no_copy_constructor_or_assign*);
public:
static const bool value = sizeof(dispatch<T>(0)) == sizeof(true_t);
};
#endif //defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <class D>
struct deleter_types
{
typedef typename add_lvalue_reference<D>::type del_ref;
typedef typename add_const_lvalue_reference<D>::type del_cref;
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
typedef typename if_c
< is_lvalue_reference<D>::value, D, del_cref >::type deleter_arg_type1;
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
typedef typename remove_reference<D>::type && deleter_arg_type2;
typedef typename remove_reference<D>::type && deleter_arg_type2;
#else
typedef ::boost::rv<D> &deleter_arg_type2;
typedef typename if_c
< is_noncopyable<D>::value, nat, del_cref>::type non_ref_deleter_arg1;
typedef typename if_c< is_lvalue_reference<D>::value
, D, non_ref_deleter_arg1 >::type deleter_arg_type1;
typedef ::boost::rv<D> & deleter_arg_type2;
#endif
};
@@ -61,10 +81,9 @@ struct deleter_types
template <class P, class D, bool = is_unary_function<D>::value || is_reference<D>::value >
struct unique_ptr_data
{
typedef typename deleter_types<D>::deleter_arg_type1 deleter_arg_type1;
typedef typename deleter_types<D>::deleter_arg_type2 deleter_arg_type2;
typedef typename deleter_types<D>::del_ref del_ref;
typedef typename deleter_types<D>::del_cref del_cref;
typedef typename deleter_types<D>::deleter_arg_type1 deleter_arg_type1;
typedef typename deleter_types<D>::del_ref del_ref;
typedef typename deleter_types<D>::del_cref del_cref;
unique_ptr_data() BOOST_NOEXCEPT
: m_p(), d()
@@ -78,13 +97,9 @@ struct unique_ptr_data
: m_p(p), d(d1)
{}
unique_ptr_data(P p, deleter_arg_type2 d2) BOOST_NOEXCEPT
: m_p(p), d(::boost::move(d2))
{}
template <class U>
unique_ptr_data(P p, BOOST_FWD_REF(U) d) BOOST_NOEXCEPT
: m_p(::boost::forward<U>(p)), d(::boost::forward<U>(d))
: m_p(p), d(::boost::forward<U>(d))
{}
del_ref deleter() { return d; }
@@ -102,16 +117,15 @@ template <class P, class D>
struct unique_ptr_data<P, D, false>
: private D
{
typedef typename deleter_types<D>::deleter_arg_type1 deleter_arg_type1;
typedef typename deleter_types<D>::deleter_arg_type2 deleter_arg_type2;
typedef typename deleter_types<D>::del_ref del_ref;
typedef typename deleter_types<D>::del_cref del_cref;
typedef typename deleter_types<D>::deleter_arg_type1 deleter_arg_type1;
typedef typename deleter_types<D>::del_ref del_ref;
typedef typename deleter_types<D>::del_cref del_cref;
unique_ptr_data() BOOST_NOEXCEPT
: D(), m_p()
{}
unique_ptr_data(P p) BOOST_NOEXCEPT
explicit unique_ptr_data(P p) BOOST_NOEXCEPT
: D(), m_p(p)
{}
@@ -119,17 +133,13 @@ struct unique_ptr_data<P, D, false>
: D(d1), m_p(p)
{}
unique_ptr_data(P p, deleter_arg_type2 d2) BOOST_NOEXCEPT
: D(::boost::move(d2)), m_p(p)
{}
template <class U>
unique_ptr_data(P p, BOOST_FWD_REF(U) d) BOOST_NOEXCEPT
: D(::boost::forward<U>(d)), m_p(p)
{}
del_ref deleter() { return static_cast<del_ref>(*this); }
del_cref deleter() const{ return static_cast<del_cref>(*this); }
del_ref deleter() BOOST_NOEXCEPT { return static_cast<del_ref>(*this); }
del_cref deleter() const BOOST_NOEXCEPT { return static_cast<del_cref>(*this); }
P m_p;
@@ -445,11 +455,8 @@ class unique_ptr
typedef move_detail::pointer_type<T, D > pointer_type_obtainer;
typedef bmd::unique_ptr_data
<typename pointer_type_obtainer::type, D> data_type;
typedef typename data_type::deleter_arg_type1 deleter_arg_type1;
typedef typename data_type::deleter_arg_type2 deleter_arg_type2;
typedef bmd::integral_constant
<bool, move_detail::is_same< D, default_delete<T> >::value > is_default_deleter_t;
typedef typename bmd::deleter_types<D>::deleter_arg_type1 deleter_arg_type1;
typedef typename bmd::deleter_types<D>::deleter_arg_type2 deleter_arg_type2;
data_type m_data;
#endif
@@ -523,10 +530,18 @@ class unique_ptr
//! - If D is an lvalue-reference type A&, then the signature is <tt>unique_ptr(pointer p, A& d)</tt>.
//! - If D is an lvalue-reference type const A&, then the signature is <tt>unique_ptr(pointer p, const A& d)</tt>.
//!
//!
//! <b>Requires</b>: Either
//! - D is not an lvalue-reference type and d is an lvalue or const rvalue.
//! D shall satisfy the requirements of CopyConstructible, and the copy constructor of D
//! shall not throw an exception. This unique_ptr will hold a copy of d.
//! - D is an lvalue-reference type and d is an lvalue. the type which D references need not be CopyConstructible nor
//! MoveConstructible. This unique_ptr will hold a D which refers to the lvalue d.
//!
//! <b>Effects</b>: Constructs a unique_ptr object which owns p, initializing the stored pointer with p and
//! initializing the deleter as described above.
//!
//! <b>Postconditions</b>: <tt>get() == p.get_deleter()</tt> returns a reference to the stored deleter. If D is a
//! <b>Postconditions</b>: <tt>get() == p</tt>. <tt>get_deleter()</tt> returns a reference to the stored deleter. If D is a
//! reference type then <tt>get_deleter()</tt> returns a reference to the lvalue d.
//!
//! <b>Remarks</b>: This constructor shall not participate in overload resolution unless:
@@ -539,6 +554,8 @@ class unique_ptr
: m_data(p, d1)
{}
//! <b>Effects</b>: Same effects as <tt>template<class Pointer> unique_ptr(Pointer p, deleter_arg_type1 d1)</tt>
//! and additionally <tt>get() == nullptr</tt>
unique_ptr(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), BOOST_MOVE_SEEDOC(deleter_arg_type1) d1) BOOST_NOEXCEPT
: m_data(pointer(), d1)
{}
@@ -548,10 +565,16 @@ class unique_ptr
//! - If D is an lvalue-reference type A&, then the signature is <tt>unique_ptr(pointer p, A&& d)</tt>.
//! - If D is an lvalue-reference type const A&, then the signature is <tt>unique_ptr(pointer p, const A&& d)</tt>.
//!
//! <b>Requires</b>: Either
//! - D is not an lvalue-reference type and d is a non-const rvalue. D
//! shall satisfy the requirements of MoveConstructible, and the move constructor
//! of D shall not throw an exception. This unique_ptr will hold a value move constructed from d.
//! - D is an lvalue-reference type and d is an rvalue, the program is ill-formed.
//!
//! <b>Effects</b>: Constructs a unique_ptr object which owns p, initializing the stored pointer with p and
//! initializing the deleter as described above.
//!
//! <b>Postconditions</b>: <tt>get() == p.get_deleter()</tt> returns a reference to the stored deleter. If D is a
//! <b>Postconditions</b>: <tt>get() == p</tt>. <tt>get_deleter()</tt> returns a reference to the stored deleter. If D is a
//! reference type then <tt>get_deleter()</tt> returns a reference to the lvalue d.
//!
//! <b>Remarks</b>: This constructor shall not participate in overload resolution unless:
@@ -564,6 +587,8 @@ class unique_ptr
: m_data(p, ::boost::move(d2))
{}
//! <b>Effects</b>: Same effects as <tt>template<class Pointer> unique_ptr(Pointer p, deleter_arg_type2 d2)</tt>
//! and additionally <tt>get() == nullptr</tt>
unique_ptr(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), BOOST_MOVE_SEEDOC(deleter_arg_type2) d2) BOOST_NOEXCEPT
: m_data(pointer(), ::boost::move(d2))
{}
@@ -657,10 +682,7 @@ class unique_ptr
//!
//! <b>Returns</b>: *this.
unique_ptr& operator=(BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) BOOST_NOEXCEPT
{
this->reset();
return *this;
}
{ this->reset(); return *this; }
//! <b>Requires</b>: <tt>get() != nullptr</tt>.
//!
@@ -668,7 +690,7 @@ class unique_ptr
//!
//! <b>Remarks</b: If T is an array type, the program is ill-formed.
BOOST_MOVE_DOC1ST(element_type&, typename bmd::add_lvalue_reference<element_type>::type)
operator*() const
operator*() const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT((!bmd::is_array<T>::value));
return *get();
@@ -680,7 +702,7 @@ class unique_ptr
//!
//! <b>Remarks</b: If T is not an array type, the program is ill-formed.
BOOST_MOVE_DOC1ST(element_type&, typename bmd::add_lvalue_reference<element_type>::type)
operator[](size_t i) const
operator[](size_t i) const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT((bmd::is_array<T>::value));
const pointer p = this->get();
@@ -698,7 +720,9 @@ class unique_ptr
pointer operator->() const BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT((!bmd::is_array<T>::value));
return get();
const pointer p = this->get();
BOOST_ASSERT(p);
return p;
}
//! <b>Returns</b>: The stored pointer.
@@ -732,7 +756,6 @@ class unique_ptr
: bmd::explicit_bool_arg(0);
}
//! <b>Postcondition</b>: <tt>get() == nullptr</tt>.
//!
//! <b>Returns</b>: The value <tt>get()</tt> had at the start of the call to release.
@@ -839,88 +862,76 @@ inline bool operator>=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
//! <b>Returns</b>:!x.
//!
template <class T1, class D1>
inline bool operator==(const unique_ptr<T1, D1> &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) BOOST_NOEXCEPT
template <class T, class D>
inline bool operator==(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) BOOST_NOEXCEPT
{ return !x; }
//! <b>Returns</b>:!x.
//!
template <class T1, class D1>
inline bool operator==(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr<T1, D1> &x) BOOST_NOEXCEPT
template <class T, class D>
inline bool operator==(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr<T, D> &x) BOOST_NOEXCEPT
{ return !x; }
//! <b>Returns</b>: (bool)x.
//!
template <class T1, class D1>
inline bool operator!=(const unique_ptr<T1, D1> &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) BOOST_NOEXCEPT
template <class T, class D>
inline bool operator!=(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) BOOST_NOEXCEPT
{ return !!x; }
//! <b>Returns</b>: (bool)x.
//!
template <class T1, class D1>
inline bool operator!=(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr<T1, D1> &x) BOOST_NOEXCEPT
template <class T, class D>
inline bool operator!=(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr<T, D> &x) BOOST_NOEXCEPT
{ return !!x; }
//! <b>Requires</b>: <tt>operator </tt> shall induce a strict weak ordering on unique_ptr<T1, D1>::pointer values.
//! <b>Requires</b>: <tt>operator </tt> shall induce a strict weak ordering on unique_ptr<T, D>::pointer values.
//!
//! <b>Returns</b>: Returns <tt>x.get() < pointer()</tt>.
template <class T1, class D1>
inline bool operator<(const unique_ptr<T1, D1> &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type))
{
typedef typename unique_ptr<T1, D1>::pointer pointer;
return x.get() < pointer();
}
template <class T, class D>
inline bool operator<(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type))
{ return x.get() < unique_ptr<T, D>::pointer(); }
//! <b>Requires</b>: <tt>operator </tt> shall induce a strict weak ordering on unique_ptr<T1, D1>::pointer values.
//! <b>Requires</b>: <tt>operator </tt> shall induce a strict weak ordering on unique_ptr<T, D>::pointer values.
//!
//! <b>Returns</b>: Returns <tt>pointer() < x.get()</tt>.
template <class T1, class D1>
inline bool operator<(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr<T1, D1> &x)
{
typedef typename unique_ptr<T1, D1>::pointer pointer;
return pointer() < x.get();
}
template <class T, class D>
inline bool operator<(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr<T, D> &x)
{ return unique_ptr<T, D>::pointer() < x.get(); }
//! <b>Returns</b>: <tt>nullptr < x</tt>.
//!
template <class T1, class D1>
inline bool operator>(const unique_ptr<T1, D1> &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type))
{
typedef typename unique_ptr<T1, D1>::pointer pointer;
return x.get() > pointer();
}
template <class T, class D>
inline bool operator>(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type))
{ return x.get() > unique_ptr<T, D>::pointer(); }
//! <b>Returns</b>: <tt>x < nullptr</tt>.
//!
template <class T1, class D1>
inline bool operator>(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr<T1, D1> &x)
{
typedef typename unique_ptr<T1, D1>::pointer pointer;
return pointer() > x.get();
}
template <class T, class D>
inline bool operator>(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr<T, D> &x)
{ return unique_ptr<T, D>::pointer() > x.get(); }
//! <b>Returns</b>: <tt>!(nullptr < x)</tt>.
//!
template <class T1, class D1>
inline bool operator<=(const unique_ptr<T1, D1> &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type))
template <class T, class D>
inline bool operator<=(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type))
{ return !(bmd::nullptr_type() < x); }
//! <b>Returns</b>: <tt>!(x < nullptr)</tt>.
//!
template <class T1, class D1>
inline bool operator<=(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr<T1, D1> &x)
template <class T, class D>
inline bool operator<=(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr<T, D> &x)
{ return !(x < bmd::nullptr_type()); }
//! <b>Returns</b>: <tt>!(x < nullptr)</tt>.
//!
template <class T1, class D1>
inline bool operator>=(const unique_ptr<T1, D1> &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type))
template <class T, class D>
inline bool operator>=(const unique_ptr<T, D> &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type))
{ return !(x < bmd::nullptr_type()); }
//! <b>Returns</b>: <tt>!(nullptr < x)</tt>.
//!
template <class T1, class D1>
inline bool operator>=(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr<T1, D1> &x)
template <class T, class D>
inline bool operator>=(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr<T, D> &x)
{ return !(bmd::nullptr_type() < x); }
} //namespace movelib {