Modify unique_ptr's constructor from convertible unique_ptr's to take the argument by value. This allows constructing unique_ptr from functions returning convertible unique_ptr's. See https://svn.boost.org/trac/boost/ticket/11259 for some details.

This commit is contained in:
Ion Gaztañaga
2015-05-06 12:32:11 +02:00
parent 69598a3d3f
commit 4a44ed3d26
4 changed files with 137 additions and 7 deletions

View File

@ -153,6 +153,14 @@
>& \
//
#define BOOST_RV_REF_BEG_IF_CXX11 \
\
//
#define BOOST_RV_REF_END_IF_CXX11 \
\
//
#define BOOST_FWD_REF(TYPE)\
const TYPE & \
//
@ -346,6 +354,19 @@
//!and ended with BOOST_RV_REF_END
#define BOOST_RV_REF_END\
&& \
//
//!This macro expands to BOOST_RV_REF_BEG if BOOST_NO_CXX11_RVALUE_REFERENCES
//!is not defined, empty otherwise
#define BOOST_RV_REF_BEG_IF_CXX11 \
BOOST_RV_REF_BEG \
//
//!This macro expands to BOOST_RV_REF_END if BOOST_NO_CXX11_RVALUE_REFERENCES
//!is not defined, empty otherwise
#define BOOST_RV_REF_END_IF_CXX11 \
BOOST_RV_REF_END \
//
//!This macro is used to achieve portable syntax in copy
//!assignment for classes marked as BOOST_COPYABLE_AND_MOVABLE.

View File

@ -219,9 +219,14 @@ struct enable_up_ptr
template<class T, class D, class U, class E>
struct unique_moveconvert_assignable
{
static const bool value = (bmupmu::extent<T>::value == bmupmu::extent<U>::value) && is_unique_ptr_convertible
< bmupmu::is_array<T>::value
, typename bmupmu::pointer_type<U, E>::type, typename bmupmu::pointer_type<T, D>::type>::value;
static const bool t_is_array = bmupmu::is_array<T>::value;
static const bool value =
t_is_array == bmupmu::is_array<U>::value &&
bmupmu::extent<T>::value == bmupmu::extent<U>::value &&
is_unique_ptr_convertible
< t_is_array
, typename bmupmu::pointer_type<U, E>::type, typename bmupmu::pointer_type<T, D>::type
>::value;
};
template<class T, class D, class U, class E, std::size_t N>
@ -290,8 +295,9 @@ struct unique_deleter_is_initializable<D, E, false>
template<class T, class D, class U, class E, class Type = bmupmu::nat>
struct enable_up_moveconv_constr
: bmupmu::enable_if_c<unique_moveconvert_assignable<T, D, U, E>::value &&
unique_deleter_is_initializable<D, E>::value, Type>
: bmupmu::enable_if_c
< unique_moveconvert_assignable<T, D, U, E>::value && unique_deleter_is_initializable<D, E>::value
, Type>
{};
} //namespace move_upd {
@ -538,7 +544,7 @@ class unique_ptr
//! <b>Postconditions</b>: <tt>get()</tt> yields the value <tt>u.get()</tt> yielded before the construction. <tt>get_deleter()</tt>
//! returns a reference to the stored deleter that was constructed from <tt>u.get_deleter()</tt>.
template <class U, class E>
unique_ptr( BOOST_RV_REF_BEG unique_ptr<U, E> BOOST_RV_REF_END u
unique_ptr( BOOST_RV_REF_BEG_IF_CXX11 unique_ptr<U, E> BOOST_RV_REF_END_IF_CXX11 u
BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_moveconv_constr<T BOOST_MOVE_I D BOOST_MOVE_I U BOOST_MOVE_I E>::type* =0)
) BOOST_NOEXCEPT
: m_data(u.release(), ::boost::move_if_not_lvalue_reference<E>(u.get_deleter()))

View File

@ -681,6 +681,107 @@ void test()
} //namespace unique_ptr_ctor_pointer_deleter_void{
////////////////////////////////
// return_unique_single_conversion
////////////////////////////////
namespace return_unique_single_conversion{
template<class T>
bml::unique_ptr<T> make_unique_ptr_of_t()
{
return bml::unique_ptr<T>(new T);
}
template<class T>
bml::unique_ptr<T const> return_const_unique_of_t()
{
return bml::unique_ptr<T const> (make_unique_ptr_of_t<T>());
}
void test()
{
reset_counters();
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<const A> p(return_const_unique_of_t<A>());
BOOST_TEST(A::count == 1);
BOOST_TEST(B::count == 0);
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<const A> p(return_const_unique_of_t<B>());
BOOST_TEST(A::count == 1);
BOOST_TEST(B::count == 1);
}
BOOST_TEST(A::count == 0);
}
} //namespace return_unique_single_conversion{
////////////////////////////////
// return_unique_array_conversion
////////////////////////////////
namespace return_unique_array_conversion{
template<class T>
bml::unique_ptr<T[]> return_unique_array_of_t(std::size_t n)
{
return bml::unique_ptr<T[]>(new T[n]);
}
template<class T>
bml::unique_ptr<const T[]> return_const_array_of_t(std::size_t n)
{
return bml::unique_ptr<const T[]>(return_unique_array_of_t<T>(n));
}
template<class T>
bml::unique_ptr<T[2]> return_unique_array_of_t_2()
{
return bml::unique_ptr<T[2]>(new T[2]);
}
template<class T>
bml::unique_ptr<const T[2]> return_const_array_of_t_2()
{
return bml::unique_ptr<const T[2]>(return_unique_array_of_t_2<T>());
}
void test()
{
reset_counters();
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<const A[]> p(return_unique_array_of_t<A>(2));
BOOST_TEST(A::count == 2);
BOOST_TEST(B::count == 0);
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<const volatile A[]> p(return_unique_array_of_t<volatile A>(2));
BOOST_TEST(A::count == 2);
BOOST_TEST(B::count == 0);
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<const volatile A[2]> p(return_const_array_of_t_2<A>());
BOOST_TEST(A::count == 2);
BOOST_TEST(B::count == 0);
}
BOOST_TEST(A::count == 0);
{
bml::unique_ptr<const volatile A[]> p(return_const_array_of_t_2<A>());
BOOST_TEST(A::count == 2);
BOOST_TEST(B::count == 0);
}
BOOST_TEST(A::count == 0);
}
} //namespace return_unique_array_conversion{
////////////////////////////////
// main
////////////////////////////////
@ -699,6 +800,8 @@ int main()
unique_ptr_ctor_pointer_deleter_dfctrdelconstref::test();
unique_ptr_ctor_pointer_deleter_convert::test();
unique_ptr_ctor_pointer_deleter_void::test();
return_unique_single_conversion::test();
return_unique_array_conversion::test();
//Test results
return boost::report_errors();

View File

@ -134,7 +134,7 @@ void test()
////////////////////////////////
// make_unique_single
// make_unique_array
////////////////////////////////
namespace make_unique_array{