From 6b2982a3856278de91c3f80d80f9649d2912525f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Wed, 27 Aug 2014 23:20:30 +0200 Subject: [PATCH 01/10] Removed unneded macros that pollute user code. --- include/boost/move/detail/config_begin.hpp | 10 +--------- include/boost/move/detail/config_end.hpp | 10 +--------- proj/vc7ide/Move.sln | 1 + 3 files changed, 3 insertions(+), 18 deletions(-) diff --git a/include/boost/move/detail/config_begin.hpp b/include/boost/move/detail/config_begin.hpp index ae3a6ff..8505f4b 100644 --- a/include/boost/move/detail/config_begin.hpp +++ b/include/boost/move/detail/config_begin.hpp @@ -10,15 +10,7 @@ #include #ifdef BOOST_MSVC - #ifndef _CRT_SECURE_NO_DEPRECATE - #define BOOST_MOVE_CRT_SECURE_NO_DEPRECATE - #define _CRT_SECURE_NO_DEPRECATE - #endif - #ifndef _SCL_SECURE_NO_WARNINGS - #define BOOST_MOVE_SCL_SECURE_NO_WARNINGS - #define _SCL_SECURE_NO_WARNINGS - #endif #pragma warning (push) - #pragma warning (disable : 4996) // "function": was declared deprecated + #pragma warning (disable : 4996) // "function": was declared deprecated (_CRT_SECURE_NO_DEPRECATE/_SCL_SECURE_NO_WARNINGS) #pragma warning (disable : 4675) // "function": resolved overload was found by argument-dependent lookup #endif diff --git a/include/boost/move/detail/config_end.hpp b/include/boost/move/detail/config_end.hpp index 5f83231..7965ef3 100644 --- a/include/boost/move/detail/config_end.hpp +++ b/include/boost/move/detail/config_end.hpp @@ -4,17 +4,9 @@ // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -// See http://www.boost.org/libs/container for documentation. +// See http://www.boost.org/libs/move for documentation. // ////////////////////////////////////////////////////////////////////////////// #if defined BOOST_MSVC #pragma warning (pop) - #ifdef BOOST_MOVE_CRT_SECURE_NO_DEPRECATE - #undef BOOST_MOVE_CRT_SECURE_NO_DEPRECATE - #undef _CRT_SECURE_NO_DEPRECATE - #endif - #ifdef BOOST_MOVE_SCL_SECURE_NO_WARNINGS - #undef BOOST_MOVE_SCL_SECURE_NO_WARNINGS - #undef _SCL_SECURE_NO_WARNINGS - #endif #endif diff --git a/proj/vc7ide/Move.sln b/proj/vc7ide/Move.sln index 0ab9b29..32eb5bb 100644 --- a/proj/vc7ide/Move.sln +++ b/proj/vc7ide/Move.sln @@ -184,6 +184,7 @@ Global ..\..\..\..\boost\move\unique_ptr.hpp = ..\..\..\..\boost\move\unique_ptr.hpp ..\..\..\..\boost\move\utility.hpp = ..\..\..\..\boost\move\utility.hpp ..\..\..\..\boost\move\utility_core.hpp = ..\..\..\..\boost\move\utility_core.hpp + ..\..\..\..\boost\move\detail\workaround.hpp = ..\..\..\..\boost\move\detail\workaround.hpp EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection From 364ee17476d4f7138afda77c46b46182586dec29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Wed, 27 Aug 2014 23:21:36 +0200 Subject: [PATCH 02/10] Simplified and improved unique_ptr implementation: - No array specialization to avoid code duplication - Constructible and assignable from literal zero --- doc/Jamfile.v2 | 5 + include/boost/move/detail/meta_utils.hpp | 84 +-- include/boost/move/detail/workaround.hpp | 4 + include/boost/move/unique_ptr.hpp | 904 ++++++++--------------- test/unique_ptr.cpp | 144 +++- test/unique_ptr_default_deleter.cpp | 4 - test/unique_ptr_functions.cpp | 121 ++- 7 files changed, 571 insertions(+), 695 deletions(-) diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index 4218cc3..29d3661 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -24,7 +24,12 @@ doxygen autodoc "PREDEFINED=\"BOOST_MOVE_DOXYGEN_INVOKED\" \\ \"BOOST_MOVE_SEEDOC(T)=see_documentation\" \\ \"BOOST_RV_REF(T)=T&&\" \\ + \"BOOST_RV_REF_BEG=\" \\ + \"BOOST_RV_REF_END=&&\" \\ \"BOOST_FWD_REF(T)=T&&\" \\ + \"BOOST_MOVE_DOC0PTR(T)=std::nullptr_t\" \\ + \"BOOST_MOVE_DOC1ST(T1, T2)=T1\" \\ + \"BOOST_MOVE_DOCIGN(T1) \"\\ " ; diff --git a/include/boost/move/detail/meta_utils.hpp b/include/boost/move/detail/meta_utils.hpp index e246ae3..6cc1763 100644 --- a/include/boost/move/detail/meta_utils.hpp +++ b/include/boost/move/detail/meta_utils.hpp @@ -313,6 +313,15 @@ struct add_lvalue_reference typedef const volatile void type; }; +template +struct add_const_lvalue_reference +{ + typedef typename remove_reference::type t_unreferenced; + typedef typename add_const::type t_unreferenced_const; + typedef typename add_lvalue_reference + ::type type; +}; + ////////////////////////////////////// // is_same @@ -483,7 +492,8 @@ struct pointer_type_imp template struct pointer_type { - typedef typename pointer_type_imp::type>::type type; + typedef typename pointer_type_imp + ::type, typename remove_reference::type>::type type; }; ////////////////////////////////////// @@ -517,7 +527,7 @@ class is_convertible #endif ////////////////////////////////////// -// is_unary_or_binary_function +// is_unary_function ////////////////////////////////////// #if defined(BOOST_MSVC) || defined(__BORLANDC_) #define BOOST_MOVE_TT_DECL __cdecl @@ -530,120 +540,86 @@ class is_convertible #endif template -struct is_unary_or_binary_function_impl +struct is_unary_function_impl { static const bool value = false; }; -// avoid duplicate definitions of is_unary_or_binary_function_impl +// avoid duplicate definitions of is_unary_function_impl #ifndef BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS template -struct is_unary_or_binary_function_impl +struct is_unary_function_impl { static const bool value = true; }; template -struct is_unary_or_binary_function_impl +struct is_unary_function_impl { static const bool value = true; }; #else // BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS template -struct is_unary_or_binary_function_impl +struct is_unary_function_impl { static const bool value = true; }; #ifndef _MANAGED template -struct is_unary_or_binary_function_impl +struct is_unary_function_impl { static const bool value = true; }; #endif template -struct is_unary_or_binary_function_impl +struct is_unary_function_impl { static const bool value = true; }; template -struct is_unary_or_binary_function_impl +struct is_unary_function_impl { static const bool value = true; }; #endif -// avoid duplicate definitions of is_unary_or_binary_function_impl +// avoid duplicate definitions of is_unary_function_impl #ifndef BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS template -struct is_unary_or_binary_function_impl +struct is_unary_function_impl { static const bool value = true; }; template -struct is_unary_or_binary_function_impl +struct is_unary_function_impl { static const bool value = true; }; #else // BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS template -struct is_unary_or_binary_function_impl +struct is_unary_function_impl { static const bool value = true; }; #ifndef _MANAGED template -struct is_unary_or_binary_function_impl +struct is_unary_function_impl { static const bool value = true; }; #endif template -struct is_unary_or_binary_function_impl +struct is_unary_function_impl { static const bool value = true; }; template -struct is_unary_or_binary_function_impl +struct is_unary_function_impl { static const bool value = true; }; #endif -// avoid duplicate definitions of is_unary_or_binary_function_impl -#ifndef BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS - -template -struct is_unary_or_binary_function_impl -{ static const bool value = true; }; - -template -struct is_unary_or_binary_function_impl -{ static const bool value = true; }; - -#else // BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS - -template -struct is_unary_or_binary_function_impl -{ static const bool value = true; }; - -#ifndef _MANAGED - -template -struct is_unary_or_binary_function_impl -{ static const bool value = true; }; - -#endif - -template -struct is_unary_or_binary_function_impl -{ static const bool value = true; }; - -template -struct is_unary_or_binary_function_impl -{ static const bool value = true; }; -#endif - template -struct is_unary_or_binary_function_impl +struct is_unary_function_impl { static const bool value = false; }; template -struct is_unary_or_binary_function -{ static const bool value = is_unary_or_binary_function_impl::value; }; +struct is_unary_function +{ static const bool value = is_unary_function_impl::value; }; } //namespace move_detail { } //namespace boost { diff --git a/include/boost/move/detail/workaround.hpp b/include/boost/move/detail/workaround.hpp index b46c808..181bc12 100644 --- a/include/boost/move/detail/workaround.hpp +++ b/include/boost/move/detail/workaround.hpp @@ -20,6 +20,10 @@ //Macros for documentation purposes. For code, expands to the argument #define BOOST_MOVE_IMPDEF(TYPE) TYPE #define BOOST_MOVE_SEEDOC(TYPE) TYPE +#define BOOST_MOVE_DOC0PTR(TYPE) TYPE +#define BOOST_MOVE_DOC1ST(TYPE1, TYPE2) TYPE2 +#define BOOST_MOVE_I , +#define BOOST_MOVE_DOCIGN(T1) T1 #include diff --git a/include/boost/move/unique_ptr.hpp b/include/boost/move/unique_ptr.hpp index 6a95155..f9b4128 100644 --- a/include/boost/move/unique_ptr.hpp +++ b/include/boost/move/unique_ptr.hpp @@ -44,29 +44,27 @@ namespace move_detail { template struct deleter_types { + typedef typename add_lvalue_reference::type del_ref; + typedef typename add_const_lvalue_reference::type del_cref; typedef typename if_c - < is_lvalue_reference::value - , D - , typename add_lvalue_reference::type>::type - >::type deleter_arg_type1; - + < is_lvalue_reference::value, D, del_cref >::type deleter_arg_type1; #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES typedef typename remove_reference::type && deleter_arg_type2; #else typedef ::boost::rv &deleter_arg_type2; #endif - typedef typename add_lvalue_reference::type deleter_lvalue_reference; - typedef typename add_lvalue_reference - ::type>::type deleter_const_lvalue_reference; }; -template ::value || is_reference::value > +//////////////////////////////////////////// +// unique_ptr_data +//////////////////////////////////////////// +template ::value || is_reference::value > struct unique_ptr_data { typedef typename deleter_types::deleter_arg_type1 deleter_arg_type1; typedef typename deleter_types::deleter_arg_type2 deleter_arg_type2; - typedef typename deleter_types::deleter_lvalue_reference deleter_lvalue_reference; - typedef typename deleter_types::deleter_const_lvalue_reference deleter_const_lvalue_reference; + typedef typename deleter_types::del_ref del_ref; + typedef typename deleter_types::del_cref del_cref; unique_ptr_data() BOOST_NOEXCEPT : m_p(), d() @@ -89,18 +87,15 @@ struct unique_ptr_data : m_p(::boost::forward(p)), d(::boost::forward(d)) {} - deleter_lvalue_reference deleter() - { return d; } - - deleter_const_lvalue_reference deleter() const - { return d; } + del_ref deleter() { return d; } + del_cref deleter() const{ return d; } P m_p; + D d; private: + unique_ptr_data& operator=(const unique_ptr_data&); unique_ptr_data(const unique_ptr_data&); - unique_ptr_data &operator=(const unique_ptr_data&); - D d; }; template @@ -109,8 +104,8 @@ struct unique_ptr_data { typedef typename deleter_types::deleter_arg_type1 deleter_arg_type1; typedef typename deleter_types::deleter_arg_type2 deleter_arg_type2; - typedef typename deleter_types::deleter_lvalue_reference deleter_lvalue_reference; - typedef typename deleter_types::deleter_const_lvalue_reference deleter_const_lvalue_reference; + typedef typename deleter_types::del_ref del_ref; + typedef typename deleter_types::del_cref del_cref; unique_ptr_data() BOOST_NOEXCEPT : D(), m_p() @@ -133,35 +128,30 @@ struct unique_ptr_data : D(::boost::forward(d)), m_p(p) {} - deleter_lvalue_reference deleter() - { return static_cast(*this); } - - deleter_const_lvalue_reference deleter() const - { return static_cast(*this); } + del_ref deleter() { return static_cast(*this); } + del_cref deleter() const{ return static_cast(*this); } P m_p; + private: + unique_ptr_data& operator=(const unique_ptr_data&); unique_ptr_data(const unique_ptr_data&); - unique_ptr_data &operator=(const unique_ptr_data&); }; +//////////////////////////////////////////// +// is_unique_ptr_convertible +//////////////////////////////////////////// + //Although non-standard, we avoid using pointer_traits //to avoid heavy dependencies template struct get_element_type { - template - static char test(int, typename X::element_type*); - - template - static int test(...); - struct DefaultWrap { typedef natify element_type; }; - + template static char test(int, typename X::element_type*); + template static int test(...); static const bool value = (1 == sizeof(test(0, 0))); - - typedef typename - if_c::type::element_type type; + typedef typename if_c::type::element_type type; }; template @@ -173,9 +163,7 @@ struct get_element_type template struct get_cvelement { - typedef typename remove_cv - ::type - >::type type; + typedef typename remove_cv::type>::type type; }; template @@ -183,46 +171,85 @@ struct is_same_cvelement_and_convertible { typedef typename remove_reference::type arg1; typedef typename remove_reference::type arg2; - static const bool same_cvless = is_same::type - ,typename get_cvelement::type - >::value; + static const bool same_cvless = + is_same::type,typename get_cvelement::type>::value; static const bool value = same_cvless && is_convertible::value; }; -template -struct enable_same_cvelement_and_convertible - : public enable_if_c - ::value, Type> +template +struct is_unique_ptr_convertible + : is_same_cvelement_and_convertible {}; +template +struct is_unique_ptr_convertible + : is_convertible +{}; -template -struct is_unique_acceptable -{ - static const bool value = OtherIsArray && - is_same_cvelement_and_convertible - ::value; -}; - -template -struct is_unique_acceptable -{ - static const bool value = !OtherIsArray && - is_convertible::value; -}; - +//////////////////////////////////////// +//// enable_def_del / enable_defdel_call +//////////////////////////////////////// template -struct enable_default_delete +struct enable_def_del : enable_if_c - < is_unique_acceptable < is_array::value - , is_array::value - , typename element_pointer::type - , typename element_pointer::type - >::value + < (is_array::value == is_array::value) && is_unique_ptr_convertible + ::value, typename remove_extent::type*, typename remove_extent::type*>::value , Type> {}; +template +struct enable_defdel_call + : public enable_def_del +{}; + +template +struct enable_defdel_call + : public enable_def_del +{}; + +//////////////////////////////////////// +//// enable_up_moveconv_assign +//////////////////////////////////////// + +template +struct enable_up_ptr + : enable_if_c< is_unique_ptr_convertible < is_array::value, FromPointer, ThisPointer>::value, Type> +{}; + +//////////////////////////////////////// +//// enable_up_moveconv_assign +//////////////////////////////////////// + +template +struct unique_moveconvert_assignable +{ + static const bool value = !is_array::value && is_unique_ptr_convertible + ::type, typename pointer_type::type>::value; +}; + +template +struct unique_moveconvert_assignable +{ + static const bool value = is_array::value && is_unique_ptr_convertible + ::type, typename pointer_type::type>::value; +}; + +template +struct enable_up_moveconv_assign + : enable_if_c::value, Type> +{}; + +//////////////////////////////////////// +//// enable_up_moveconv_constr +//////////////////////////////////////// + +template::value> +struct unique_deleter_is_initializable +{ + static const bool value = is_same::value; +}; + template class is_rvalue_convertible { @@ -245,12 +272,6 @@ class is_rvalue_convertible static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t); }; -template::value> -struct unique_deleter_is_initializable -{ - static const bool value = is_same::value; -}; - template struct unique_deleter_is_initializable { @@ -274,87 +295,33 @@ struct unique_deleter_is_initializable #endif }; -template -struct is_ptr_convertible -{ - typedef typename ::boost::move_detail::pointer_type::type from_ptr; - typedef typename ::boost::move_detail::pointer_type::type to_ptr; - static const bool value = is_convertible::value; -}; - -template -struct unique_moveconvert_assignable -{ - static const bool ptrconvert = is_ptr_convertible::value; - static const bool notarray = !is_array::value; - static const bool value = ptrconvert && notarray; -}; - -template -struct unique_moveconvert_constructible -{ - static const bool massignable = unique_moveconvert_assignable::value; - static const bool value = massignable && unique_deleter_is_initializable::value; -}; - template -struct enable_unique_moveconvert_constructible - : enable_if_c - < unique_moveconvert_constructible::value, Type> +struct enable_up_moveconv_constr + : enable_if_c::value && + unique_deleter_is_initializable::value, Type> {}; -template -struct enable_unique_moveconvert_assignable - : enable_if_c - < unique_moveconvert_assignable::value, Type> -{}; +//////////////////////////////////////// +//// Some bool literal zero conversion utilities +//////////////////////////////////////// -template -struct uniquearray_moveconvert_assignable -{ - typedef typename ::boost::move_detail::pointer_type::type from_ptr; - typedef typename ::boost::move_detail::pointer_type::type to_ptr; - static const bool ptrconvert = is_same_cvelement_and_convertible::value; - static const bool yesarray = is_array::value; - static const bool value = ptrconvert && yesarray; -}; +struct bool_conversion {int for_bool; int for_arg(); }; +typedef int bool_conversion::* explicit_bool_arg; -template -struct uniquearray_moveconvert_constructible -{ - static const bool massignable = uniquearray_moveconvert_assignable::value; - static const bool value = massignable && unique_deleter_is_initializable::value; -}; - -template -struct enable_uniquearray_moveconvert_constructible - : enable_if_c - < uniquearray_moveconvert_constructible::value, Type> -{}; - -template -struct enable_uniquearray_moveconvert_assignable - : enable_if_c - < uniquearray_moveconvert_assignable::value, Type> -{}; - -template -void unique_ptr_call_deleter(Deleter &d, const Pointer &p, boost::move_detail::true_type) //default_deleter -{ d(p); } - -template -void unique_ptr_call_deleter(Deleter &d, const Pointer &p, boost::move_detail::false_type) -{ if(p) d(p); } +#if !defined(BOOST_NO_CXX11_NULLPTR) +typedef std::nullptr_t nullptr_type; +#else +typedef int (bool_conversion::*nullptr_type)(); +#endif } //namespace move_detail { namespace movelib { +namespace bmd = boost::move_detail; + //!The class template default_delete serves as the default deleter //!(destruction policy) for the class template unique_ptr. -//! -//!A specialization to delete array types is provided -//!with a slightly altered interface. template struct default_delete { @@ -375,138 +342,48 @@ struct default_delete default_delete(const default_delete&) BOOST_NOEXCEPT = default; default_delete &operator=(const default_delete&) BOOST_NOEXCEPT = default; #else - typedef T element_type; + typedef typename bmd::remove_extent::type element_type; #endif //! Effects: Constructs a default_delete object from another default_delete object. //! - //! Remarks: This constructor shall not participate in overload resolution unless U* is - //! implicitly convertible to T*. + //! Remarks: This constructor shall not participate in overload resolution unless: + //! - If T is not an array type and U* is implicitly convertible to T*. + //! - If T is an array type and U* is a more CV qualified pointer to remove_extent::type. template default_delete(const default_delete& - #if !defined(BOOST_MOVE_DOXYGEN_INVOKED) - , typename ::boost::move_detail::enable_default_delete::type* = 0 - #endif + BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmd::enable_def_del::type* =0) ) BOOST_NOEXCEPT {} //! Effects: Constructs a default_delete object from another default_delete object. //! - //! Remarks: This constructor shall not participate in overload resolution unless U* is - //! implicitly convertible to T*. - //! - //! Note: Non-standard extension + //! Remarks: This constructor shall not participate in overload resolution unless: + //! - If T is not an array type and U* is implicitly convertible to T*. + //! - If T is an array type and U* is a more CV qualified pointer to remove_extent::type. template - #if defined(BOOST_MOVE_DOXYGEN_INVOKED) - default_delete & - #else - typename ::boost::move_detail::enable_default_delete::type - #endif + BOOST_MOVE_DOC1ST(default_delete&, + typename bmd::enable_def_del::type) operator=(const default_delete&) BOOST_NOEXCEPT { return *this; } - //! Effects: calls delete on ptr. + //! Effects: if T is not an array type, calls delete on static_cast(ptr), + //! otherwise calls delete[] on static_cast::type*>(ptr). //! - //! Remarks: If T is an incomplete type, the program is ill-formed. - void operator()(T* ptr) const - { - //T must be a complete type - BOOST_STATIC_ASSERT(sizeof(T) > 0); - delete ptr; - } -}; - -//!The specialization to delete array types (array_of_T = T[]) -//!with a slightly altered interface. -//! -//! \tparam array_of_T is an alias for types of form T[] -template -struct default_delete -#if defined(BOOST_MOVE_DOXYGEN_INVOKED) - -#else - -#endif -{ - //! Default constructor. - //! - BOOST_CONSTEXPR default_delete() - //Avoid "defaulted on its first declaration must not have an exception-specification" error for GCC 4.6 - #if !defined(BOOST_GCC) || (BOOST_GCC < 40600 && BOOST_GCC >= 40700) || defined(BOOST_MOVE_DOXYGEN_INVOKED) - BOOST_NOEXCEPT - #endif - #if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || defined(BOOST_MOVE_DOXYGEN_INVOKED) - = default; - #else - {}; - #endif - - #if defined(BOOST_MOVE_DOXYGEN_INVOKED) - default_delete(const default_delete&) BOOST_NOEXCEPT = default; - default_delete &operator=(const default_delete&) BOOST_NOEXCEPT = default; - #else - typedef T element_type; - #endif - - //! Effects: Constructs a default_delete object from another default_delete object. - //! - //! Remarks: This constructor shall not participate in overload resolution unless U* is - //! a more CV cualified pointer to T. - //! - //! Note: Non-standard extension + //! Remarks: If U is an incomplete type, the program is ill-formed. + //! This operator shall not participate in overload resolution unless: + //! - T is not an array type and U* is convertible to T*, OR + //! - T is an array type, and remove_cv::type is the same type as + //! remove_cv::type>::type and U* is convertible to remove_extent::type*. template - default_delete(const default_delete& - #if !defined(BOOST_MOVE_DOXYGEN_INVOKED) - , typename ::boost::move_detail::enable_default_delete::type* = 0 - #endif - ) BOOST_NOEXCEPT - {} - - //! Effects: Constructs a default_delete object from another default_delete object. - //! - //! Remarks: This constructor shall not participate in overload resolution unless U* is - //! a more CV cualified pointer to T. - //! - //! Note: Non-standard extension - template - #if defined(BOOST_MOVE_DOXYGEN_INVOKED) - default_delete & - #else - typename ::boost::move_detail::enable_default_delete::type - #endif - operator=(const default_delete&) BOOST_NOEXCEPT - { return *this; } - - #if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_MOVE_DOXYGEN_INVOKED) - //! Effects: calls delete[] on ptr. - //! - //! Remarks: If T is an incomplete type, the program is ill-formed. - void operator()(T* ptr) const - { - //T must be a complete type - BOOST_STATIC_ASSERT(sizeof(T) > 0); - delete [] ptr; - } - - //! Remarks: This deleter can't delete pointers convertible to T unless U* is - //! a more CV cualified pointer to T. - //! - //! Note: Non-standard extension - template - void operator()(U*) const = delete; - #else - template - void operator()(U* ptr - #if !defined(BOOST_MOVE_DOXYGEN_INVOKED) - , typename ::boost::move_detail::enable_default_delete::type * = 0 - #endif - ) const BOOST_NOEXCEPT + BOOST_MOVE_DOC1ST(void, typename bmd::enable_defdel_call::type) + operator()(U* ptr) const BOOST_NOEXCEPT { //U must be a complete type BOOST_STATIC_ASSERT(sizeof(U) > 0); - delete [] ptr; + element_type * const p = static_cast(ptr); + bmd::is_array::value ? delete [] p : delete p; } - #endif }; @@ -541,6 +418,11 @@ struct default_delete //! ownership of dynamically allocated memory to a function, and returning dynamically allocated memory from //! a function. //! +//! If T is an array type (e.g. unique_ptr) the interface is slightly altered: +//! - Pointers to types derived from T are rejected by the constructors, and by reset. +//! - The observers operator* and operator-> are not provided. +//! - The indexing observer operator[] is provided. +//! //! \tparam T Provides the type of the stored pointer. //! \tparam D The deleter type: //! - The default type for the template parameter D is default_delete. A client-supplied template argument @@ -559,15 +441,16 @@ class unique_ptr private: #else BOOST_MOVABLE_BUT_NOT_COPYABLE(unique_ptr) - typedef move_detail::pointer_type pointer_type_obtainer; - typedef ::boost::move_detail::unique_ptr_data - data_type; - typedef typename data_type::deleter_arg_type1 deleter_arg_type1; - typedef typename data_type::deleter_arg_type2 deleter_arg_type2; - typedef typename data_type::deleter_lvalue_reference deleter_lvalue_reference; - typedef typename data_type::deleter_const_lvalue_reference deleter_const_lvalue_reference; - struct nat {int for_bool;}; - typedef ::boost::move_detail::integral_constant >::value > is_default_deleter_t; + + typedef move_detail::pointer_type pointer_type_obtainer; + typedef bmd::unique_ptr_data + 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 + >::value > is_default_deleter_t; + data_type m_data; #endif public: @@ -575,7 +458,9 @@ class unique_ptr //! synonym for remove_reference::type::pointer. Otherwise it shall be a //! synonym for T*. typedef typename BOOST_MOVE_SEEDOC(pointer_type_obtainer::type) pointer; - typedef T element_type; + //! If T is an array type, then element_type is equal to T. Otherwise, if T is a type + //! in the form U[], element_type is equal to U. + typedef typename BOOST_MOVE_SEEDOC(bmd::remove_extent::type) element_type; typedef D deleter_type; //! Requires: D shall satisfy the requirements of DefaultConstructible, and @@ -593,8 +478,19 @@ class unique_ptr { //If this constructor is instantiated with a pointer type or reference type //for the template argument D, the program is ill-formed. - BOOST_STATIC_ASSERT(!::boost::move_detail::is_pointer::value); - BOOST_STATIC_ASSERT(!::boost::move_detail::is_reference::value); + BOOST_STATIC_ASSERT(!bmd::is_pointer::value); + BOOST_STATIC_ASSERT(!bmd::is_reference::value); + } + + //! Effects: Same as unique_ptr() (default constructor). + //! + BOOST_CONSTEXPR unique_ptr(BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) BOOST_NOEXCEPT + : m_data() + { + //If this constructor is instantiated with a pointer type or reference type + //for the template argument D, the program is ill-formed. + BOOST_STATIC_ASSERT(!bmd::is_pointer::value); + BOOST_STATIC_ASSERT(!bmd::is_reference::value); } //! Requires: D shall satisfy the requirements of DefaultConstructible, and @@ -606,14 +502,20 @@ class unique_ptr //! Postconditions: get() == p. get_deleter() returns a reference to the stored deleter. //! //! Remarks: If this constructor is instantiated with a pointer type or reference type - //! for the template argument D, the program is ill-formed. - explicit unique_ptr(pointer p) BOOST_NOEXCEPT + //! for the template argument D, the program is ill-formed. + //! This constructor shall not participate in overload resolution unless: + //! - If T is not an array type and Pointer is implicitly convertible to pointer. + //! - If T is an array type and Pointer is a more CV qualified pointer to element_type. + template + explicit unique_ptr(Pointer p + BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmd::enable_up_ptr::type* =0) + ) BOOST_NOEXCEPT : m_data(p) { //If this constructor is instantiated with a pointer type or reference type //for the template argument D, the program is ill-formed. - BOOST_STATIC_ASSERT(!::boost::move_detail::is_pointer::value); - BOOST_STATIC_ASSERT(!::boost::move_detail::is_reference::value); + BOOST_STATIC_ASSERT(!bmd::is_pointer::value); + BOOST_STATIC_ASSERT(!bmd::is_reference::value); } //!The signature of this constructor depends upon whether D is a reference type. @@ -626,10 +528,21 @@ class unique_ptr //! //! Postconditions: get() == p.get_deleter() returns a reference to the stored deleter. If D is a //! reference type then get_deleter() returns a reference to the lvalue d. - unique_ptr(pointer p, BOOST_MOVE_SEEDOC(deleter_arg_type1) d1) BOOST_NOEXCEPT + //! + //! Remarks: This constructor shall not participate in overload resolution unless: + //! - If T is not an array type and Pointer is implicitly convertible to pointer. + //! - If T is an array type and Pointer is a more CV qualified pointer to element_type. + template + unique_ptr(Pointer p, BOOST_MOVE_SEEDOC(deleter_arg_type1) d1 + BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmd::enable_up_ptr::type* =0) + ) BOOST_NOEXCEPT : m_data(p, d1) {} + unique_ptr(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), BOOST_MOVE_SEEDOC(deleter_arg_type1) d1) BOOST_NOEXCEPT + : m_data(pointer(), d1) + {} + //! The signature of this constructor depends upon whether D is a reference type. //! - If D is non-reference type A, then the signature is unique_ptr(pointer p, A&& d). //! - If D is an lvalue-reference type A&, then the signature is unique_ptr(pointer p, A&& d). @@ -640,10 +553,21 @@ class unique_ptr //! //! Postconditions: get() == p.get_deleter() returns a reference to the stored deleter. If D is a //! reference type then get_deleter() returns a reference to the lvalue d. - unique_ptr(pointer p, BOOST_MOVE_SEEDOC(deleter_arg_type2) d2) BOOST_NOEXCEPT + //! + //! Remarks: This constructor shall not participate in overload resolution unless: + //! - If T is not an array type and Pointer is implicitly convertible to pointer. + //! - If T is an array type and Pointer is a more CV qualified pointer to element_type. + template + unique_ptr(Pointer p, BOOST_MOVE_SEEDOC(deleter_arg_type2) d2 + BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmd::enable_up_ptr::type* =0) + ) BOOST_NOEXCEPT : m_data(p, ::boost::move(d2)) {} + unique_ptr(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), BOOST_MOVE_SEEDOC(deleter_arg_type2) d2) BOOST_NOEXCEPT + : m_data(pointer(), ::boost::move(d2)) + {} + //! Requires: If D is not a reference type, D shall satisfy the requirements of MoveConstructible. //! Construction of the deleter from an rvalue of type D shall not throw an exception. //! @@ -658,19 +582,6 @@ class unique_ptr : m_data(u.release(), ::boost::move_if_not_lvalue_reference(u.get_deleter())) {} - #if !defined(BOOST_NO_CXX11_NULLPTR) || defined(BOOST_MOVE_DOXYGEN_INVOKED) - //! Effects: Same as unique_ptr() (default constructor). - //! - BOOST_CONSTEXPR unique_ptr(std::nullptr_t) BOOST_NOEXCEPT - : m_data() - { - //If this constructor is instantiated with a pointer type or reference type - //for the template argument D, the program is ill-formed. - BOOST_STATIC_ASSERT(!::boost::move_detail::is_pointer::value); - BOOST_STATIC_ASSERT(!::boost::move_detail::is_reference::value); - } - #endif - //! Requires: If E is not a reference type, construction of the deleter from an rvalue of type E shall be //! well formed and shall not throw an exception. Otherwise, E is a reference type and construction of the //! deleter from an lvalue of type E shall be well formed and shall not throw an exception. @@ -688,9 +599,7 @@ class unique_ptr //! returns a reference to the stored deleter that was constructed from u.get_deleter(). template unique_ptr( BOOST_RV_REF_BEG unique_ptr BOOST_RV_REF_END u - #if !defined(BOOST_MOVE_DOXYGEN_INVOKED) - , typename ::boost::move_detail::enable_unique_moveconvert_constructible::type * = 0 - #endif + BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmd::enable_up_moveconv_constr::type* =0) ) BOOST_NOEXCEPT : m_data(u.release(), ::boost::move_if_not_lvalue_reference(u.get_deleter())) {} @@ -702,7 +611,7 @@ class unique_ptr //! //! Note: The use of default_delete requires T to be a complete type ~unique_ptr() - { unique_ptr_call_deleter(m_data.deleter(), m_data.m_p, is_default_deleter_t()); } + { if(m_data.m_p) m_data.deleter()(m_data.m_p); } //! Requires: If D is not a reference type, D shall satisfy the requirements of MoveAssignable //! and assignment of the deleter from an rvalue of type D shall not throw an exception. Otherwise, D @@ -733,11 +642,8 @@ class unique_ptr //! //! Returns: *this. template - #if defined(BOOST_MOVE_DOXYGEN_INVOKED) - unique_ptr& - #else - typename ::boost::move_detail::enable_unique_moveconvert_assignable::type - #endif + BOOST_MOVE_DOC1ST(unique_ptr&, typename bmd::enable_up_moveconv_assign + ::type) operator=(BOOST_RV_REF_BEG unique_ptr BOOST_RV_REF_END u) BOOST_NOEXCEPT { this->reset(u.release()); @@ -745,50 +651,55 @@ class unique_ptr return *this; } - #if !defined(BOOST_NO_CXX11_NULLPTR) || defined(BOOST_MOVE_DOXYGEN_INVOKED) //! Effects: reset(). //! //! Postcondition: get() == nullptr //! //! Returns: *this. - unique_ptr& operator=(std::nullptr_t) BOOST_NOEXCEPT + unique_ptr& operator=(BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) BOOST_NOEXCEPT { this->reset(); return *this; } - #else - //! Effects: reset(). - //! - //! Postcondition: get() == nullptr - //! - //! - //! Note: Non-standard extension to use 0 as nullptr - unique_ptr& operator=(int nat::*) BOOST_NOEXCEPT - { - this->reset(); - return *this; - } - #endif - //! Requires: get() != nullptr. //! //! Returns: *get(). - #if defined(BOOST_MOVE_DOXYGEN_INVOKED) - add_lvalue_reference_t - #else - typename ::boost::move_detail::add_lvalue_reference::type - #endif + //! + //! Remarks::type) operator*() const - { return *get(); } + { + BOOST_STATIC_ASSERT((!bmd::is_array::value)); + return *get(); + } + + //! Requires: i < the number of elements in the array to which the stored pointer points. + //! + //! Returns: get()[i]. + //! + //! Remarks::type) + operator[](size_t i) const + { + BOOST_STATIC_ASSERT((bmd::is_array::value)); + const pointer p = this->get(); + BOOST_ASSERT(p); + return p[i]; + } //! Requires: get() != nullptr. //! //! Returns: get(). //! //! Note: use typically requires that T be a complete type. + //! + //! Remarks() const BOOST_NOEXCEPT - { return get(); } + { + BOOST_STATIC_ASSERT((!bmd::is_array::value)); + return get(); + } //! Returns: The stored pointer. //! @@ -797,22 +708,30 @@ class unique_ptr //! Returns: A reference to the stored deleter. //! - deleter_lvalue_reference get_deleter() BOOST_NOEXCEPT - { return m_data.deleter(); } + BOOST_MOVE_DOC1ST(D&, typename bmd::add_lvalue_reference::type) + get_deleter() BOOST_NOEXCEPT + { return m_data.deleter(); } //! Returns: A reference to the stored deleter. //! - deleter_const_lvalue_reference get_deleter() const BOOST_NOEXCEPT + BOOST_MOVE_DOC1ST(const D&, typename bmd::add_const_lvalue_reference::type) + get_deleter() const BOOST_NOEXCEPT { return m_data.deleter(); } #ifdef BOOST_MOVE_DOXYGEN_INVOKED //! Returns: Returns: get() != nullptr. //! - explicit operator bool() const BOOST_NOEXCEPT; + explicit operator bool #else - operator int nat::*() const BOOST_NOEXCEPT - { return m_data.m_p ? &nat::for_bool : (int nat::*)0; } + operator bmd::explicit_bool_arg #endif + ()const BOOST_NOEXCEPT + { + return m_data.m_p + ? &bmd::bool_conversion::for_bool + : bmd::explicit_bool_arg(0); + } + //! Postcondition: get() == nullptr. //! @@ -833,263 +752,45 @@ class unique_ptr //! //! Postconditions: get() == p. Note: The postcondition does not hold if the call to get_deleter() //! destroys *this since this->get() is no longer a valid expression. - void reset(pointer p = pointer()) BOOST_NOEXCEPT + //! + //! Remarks: This constructor shall not participate in overload resolution unless: + //! - If T is not an array type and Pointer is implicitly convertible to pointer. + //! - If T is an array type and Pointer is a more CV qualified pointer to element_type. + template + BOOST_MOVE_DOC1ST(void, typename bmd::enable_up_ptr::type) + reset(Pointer p) BOOST_NOEXCEPT { pointer tmp = m_data.m_p; m_data.m_p = p; - unique_ptr_call_deleter(m_data.deleter(), tmp, is_default_deleter_t()); + if(tmp) m_data.deleter()(tmp); } + //! Requires: The expression get_deleter()(get()) shall be well formed, shall have well-defined behavior, + //! and shall not throw exceptions. + //! + //! Effects: assigns nullptr to the stored pointer, and then if the old value of the stored pointer, old_p, was not + //! equal to nullptr, calls get_deleter()(old_p). Note: The order of these operations is significant + //! because the call to get_deleter() may destroy *this. + //! + //! Postconditions: get() == p. Note: The postcondition does not hold if the call to get_deleter() + //! destroys *this since this->get() is no longer a valid expression. + void reset() BOOST_NOEXCEPT + { this->reset(pointer()); } + + //! Effects: Same as reset() + //! + void reset(BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) BOOST_NOEXCEPT + { this->reset(); } + //! Requires: get_deleter() shall be swappable and shall not throw an exception under swap. //! //! Effects: Invokes swap on the stored pointers and on the stored deleters of *this and u. void swap(unique_ptr& u) BOOST_NOEXCEPT { - using boost::move_detail::swap; + using bmd::swap; swap(m_data.m_p, u.m_data.m_p); swap(m_data.deleter(), u.m_data.deleter()); } - - #if !defined(BOOST_MOVE_DOXYGEN_INVOKED) - data_type m_data; - #endif -}; - -//!A specialization for array types (array_of_T = T[]) is provided with a slightly altered interface. -//! - Conversions between different types of unique_ptr or to or from the non-array forms of -//! unique_ptr produce an ill-formed program. -//! - Pointers to types derived from T are rejected by the constructors, and by reset. -//! - The observers operator* and operator-> are not provided. -//! - The indexing observer operator[] is provided. -//! - The default deleter will call delete[]. -//! -//! Descriptions are provided below only for member functions that have behavior different from the primary template. -//! -//! \tparam array_of_T is an alias for types of form T[]. The template argument T shall be a complete type. -template -class unique_ptr -#if defined(BOOST_MOVE_DOXYGEN_INVOKED) -< array_of_T -#else -< T[] -#endif -, D> -{ - #if defined(BOOST_MOVE_DOXYGEN_INVOKED) - public: - unique_ptr(const unique_ptr&) = delete; - unique_ptr& operator=(const unique_ptr&) = delete; - private: - #else - BOOST_MOVABLE_BUT_NOT_COPYABLE(unique_ptr) - typedef ::boost::move_detail::pointer_type pointer_type_obtainer; - typedef ::boost::move_detail::unique_ptr_data - data_type; - typedef typename data_type::deleter_arg_type1 deleter_arg_type1; - typedef typename data_type::deleter_arg_type2 deleter_arg_type2; - typedef typename data_type::deleter_lvalue_reference deleter_lvalue_reference; - typedef typename data_type::deleter_const_lvalue_reference deleter_const_lvalue_reference; - struct nat {int for_bool;}; - typedef ::boost::move_detail::integral_constant >::value > is_default_deleter_t; - #endif - - public: - typedef typename BOOST_MOVE_SEEDOC(pointer_type_obtainer::type) pointer; - typedef T element_type; - typedef D deleter_type; - - BOOST_CONSTEXPR unique_ptr() BOOST_NOEXCEPT - : m_data() - { - //If this constructor is instantiated with a pointer type or reference type - //for the template argument D, the program is ill-formed. - BOOST_STATIC_ASSERT(!::boost::move_detail::is_pointer::value); - BOOST_STATIC_ASSERT(!::boost::move_detail::is_reference::value); - } - - //! This constructor behave the same as in the primary template except that it does - //! not accept pointer types which are convertible to pointer. - #if defined(BOOST_MOVE_DOXYGEN_INVOKED) - unique_ptr(pointer p); - #else - template - explicit unique_ptr(P p - ,typename ::boost::move_detail::enable_same_cvelement_and_convertible::type* = 0 - ) BOOST_NOEXCEPT - : m_data(p) - { - BOOST_STATIC_ASSERT(!::boost::move_detail::is_pointer::value); - BOOST_STATIC_ASSERT(!::boost::move_detail::is_reference::value); - } - #endif - - //! This constructor behave the same as in the primary template except that it does - //! not accept pointer types which are convertible to pointer. - #if defined(BOOST_MOVE_DOXYGEN_INVOKED) - unique_ptr(pointer p, BOOST_MOVE_SEEDOC(deleter_arg_type1) d1); - #else - template - unique_ptr(P p, BOOST_MOVE_SEEDOC(deleter_arg_type1) d1 - ,typename ::boost::move_detail::enable_same_cvelement_and_convertible::type* = 0 - ) BOOST_NOEXCEPT - : m_data(p, d1) - {} - #endif - - //! This assignement behave the same as in the primary template except that it does - //! only accept pointer types which are equal or less cv qualified than pointer - #if defined(BOOST_MOVE_DOXYGEN_INVOKED) - unique_ptr(pointer p, BOOST_MOVE_SEEDOC(deleter_arg_type2) d2); - #else - template - unique_ptr(P p, BOOST_MOVE_SEEDOC(deleter_arg_type2) d2 - ,typename ::boost::move_detail::enable_same_cvelement_and_convertible::type* = 0 - ) BOOST_NOEXCEPT - : m_data(p, ::boost::move(d2)) - {} - #endif - - unique_ptr(BOOST_RV_REF(unique_ptr) u) BOOST_NOEXCEPT - : m_data(u.release(), ::boost::move_if_not_lvalue_reference(u.get_deleter())) - {} - - //! This assignement behave the same as in the primary template except that it does - //! only accept pointer types which are equal or less cv qualified than pointer. - //! - //! Note: Non-standard extension - template - unique_ptr( BOOST_RV_REF_BEG unique_ptr BOOST_RV_REF_END u - #if !defined(BOOST_MOVE_DOXYGEN_INVOKED) - , typename ::boost::move_detail::enable_uniquearray_moveconvert_constructible::type * = 0 - #endif - ) BOOST_NOEXCEPT - : m_data(u.release(), ::boost::move_if_not_lvalue_reference(u.get_deleter())) - {} - - #if !defined(BOOST_NO_CXX11_NULLPTR) || defined(BOOST_MOVE_DOXYGEN_INVOKED) - BOOST_CONSTEXPR unique_ptr(std::nullptr_t) BOOST_NOEXCEPT - : m_data() - { - //If this constructor is instantiated with a pointer type or reference type - //for the template argument D, the program is ill-formed. - BOOST_STATIC_ASSERT(!::boost::move_detail::is_pointer::value); - BOOST_STATIC_ASSERT(!::boost::move_detail::is_reference::value); - } - #endif - - ~unique_ptr() - { - unique_ptr_call_deleter(m_data.deleter(), m_data.m_p, is_default_deleter_t()); - } - - unique_ptr& operator=(BOOST_RV_REF(unique_ptr) u) BOOST_NOEXCEPT - { - this->reset(u.release()); - m_data.deleter() = ::boost::move_if_not_lvalue_reference(u.get_deleter()); - return *this; - } - - //! This assignement behave the same as in the primary template except that it does - //! only accept pointer types which are equal or less cv qualified than pointer - //! - //! Note: Non-standard extension - template - #if defined(BOOST_MOVE_DOXYGEN_INVOKED) - unique_ptr& - #else - typename ::boost::move_detail::enable_uniquearray_moveconvert_assignable::type - #endif - operator=(BOOST_RV_REF_BEG unique_ptr BOOST_RV_REF_END u) BOOST_NOEXCEPT - { - this->reset(u.release()); - m_data.deleter() = ::boost::move_if_not_lvalue_reference(u.get_deleter()); - return *this; - } - - #if !defined(BOOST_NO_CXX11_NULLPTR) || defined(BOOST_MOVE_DOXYGEN_INVOKED) - unique_ptr& operator=(std::nullptr_t) BOOST_NOEXCEPT - { - this->reset(); - return *this; - } - #else - unique_ptr& operator=(int nat::*) BOOST_NOEXCEPT - { - this->reset(); - return *this; - } - #endif - - //! Requires: i < the number of elements in the array to which the stored pointer points. - //! Returns: get()[i]. - T& operator[](size_t i) const - { - const pointer p = this->get(); - BOOST_ASSERT(p); - return p[i]; - } - - pointer get() const BOOST_NOEXCEPT - { return m_data.m_p; } - - deleter_lvalue_reference get_deleter() BOOST_NOEXCEPT - { return m_data.deleter(); } - - deleter_const_lvalue_reference get_deleter() const BOOST_NOEXCEPT - { return m_data.deleter(); } - - #ifdef BOOST_MOVE_DOXYGEN_INVOKED - explicit operator bool() const BOOST_NOEXCEPT; - #else - operator int nat::*() const BOOST_NOEXCEPT - { return m_data.m_p ? &nat::for_bool : (int nat::*)0; } - #endif - - pointer release() BOOST_NOEXCEPT - { - const pointer tmp = m_data.m_p; - m_data.m_p = pointer(); - return tmp; - } - - #if defined(BOOST_MOVE_DOXYGEN_INVOKED) - void reset(pointer p = pointer()); - #else - template - void reset(P p - ,typename ::boost::move_detail::enable_same_cvelement_and_convertible::type* = 0 - ) BOOST_NOEXCEPT - { - pointer tmp = m_data.m_p; - m_data.m_p = p; - unique_ptr_call_deleter(m_data.deleter(), tmp, is_default_deleter_t()); - } - - void reset() BOOST_NOEXCEPT - { - pointer tmp = m_data.m_p; - m_data.m_p = pointer(); - unique_ptr_call_deleter(m_data.deleter(), tmp, is_default_deleter_t()); - } - #endif - - #if !defined(BOOST_NO_CXX11_NULLPTR) || defined(BOOST_MOVE_DOXYGEN_INVOKED) - void reset(std::nullptr_t) BOOST_NOEXCEPT - { this->reset(); } - #endif - - void swap(unique_ptr& u) BOOST_NOEXCEPT - { - using boost::move_detail::swap; - swap(m_data.m_p, u.m_data.m_p); - swap(m_data.deleter(), u.m_data.deleter()); - } - - #if defined(BOOST_MOVE_DOXYGEN_INVOKED) - template void reset(U) = delete; - #else - data_type m_data; - #endif }; //! Effects: Calls x.swap(y). @@ -1110,32 +811,13 @@ template inline bool operator!=(const unique_ptr &x, const unique_ptr &y) { return x.get() != y.get(); } -#if 0 -//! Requires: Let CT be common_type::pointer, unique_ptr::pointer>:: -//! type. Then the specialization less shall be a function object type that induces a -//! strict weak ordering on the pointer values. -//! -//! Returns: less()(x.get(), y.get()). -//! -//! Remarks: If unique_ptr::pointer is not implicitly convertible to CT or -//! unique_ptr::pointer is not implicitly convertible to CT, the program is ill-formed. -#else //! Returns: x.get() < y.get(). //! -//! Remarks: This comparison shall induces a -//! strict weak ordering on the pointer values. -#endif +//! Remarks: This comparison shall induce a +//! strict weak ordering betwen pointers. template inline bool operator<(const unique_ptr &x, const unique_ptr &y) -{ - #if 0 - typedef typename common_type - < typename unique_ptr::pointer - , typename unique_ptr::pointer>::type CT; - return std::less()(x.get(), y.get());*/ - #endif - return x.get() < y.get(); -} +{ return x.get() < y.get(); } //! Returns: !(y < x). //! @@ -1155,49 +837,45 @@ template inline bool operator>=(const unique_ptr &x, const unique_ptr &y) { return !(x < y); } -#if !defined(BOOST_NO_CXX11_NULLPTR) || defined(BOOST_MOVE_DOXYGEN_INVOKED) - //! Returns:!x. //! template -inline bool operator==(const unique_ptr &x, std::nullptr_t) BOOST_NOEXCEPT +inline bool operator==(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) BOOST_NOEXCEPT { return !x; } //! Returns:!x. //! template -inline bool operator==(std::nullptr_t, const unique_ptr &x) BOOST_NOEXCEPT +inline bool operator==(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr &x) BOOST_NOEXCEPT { return !x; } //! Returns: (bool)x. //! template -inline bool operator!=(const unique_ptr &x, std::nullptr_t) BOOST_NOEXCEPT +inline bool operator!=(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) BOOST_NOEXCEPT { return !!x; } //! Returns: (bool)x. //! template -inline bool operator!=(std::nullptr_t, const unique_ptr &x) BOOST_NOEXCEPT +inline bool operator!=(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr &x) BOOST_NOEXCEPT { return !!x; } -//! Requires: The specialization less::pointer> shall be a function object type -//! that induces a strict weak ordering on the pointer values. +//! Requires: operator shall induce a strict weak ordering on unique_ptr::pointer values. //! -//! Returns: less::pointer>()(x.get(), nullptr). +//! Returns: Returns x.get() < pointer(). template -inline bool operator<(const unique_ptr &x, std::nullptr_t) +inline bool operator<(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) { typedef typename unique_ptr::pointer pointer; return x.get() < pointer(); } -//! Requires: The specialization less::pointer> shall be a function object type -//! that induces a strict weak ordering on the pointer values. +//! Requires: operator shall induce a strict weak ordering on unique_ptr::pointer values. //! -//! Returns: The second function template returns less::pointer>()(nullptr, x.get()). +//! Returns: Returns pointer() < x.get(). template -inline bool operator<(std::nullptr_t, const unique_ptr &x) +inline bool operator<(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr &x) { typedef typename unique_ptr::pointer pointer; return pointer() < x.get(); @@ -1206,7 +884,7 @@ inline bool operator<(std::nullptr_t, const unique_ptr &x) //! Returns: nullptr < x. //! template -inline bool operator>(const unique_ptr &x, std::nullptr_t) +inline bool operator>(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) { typedef typename unique_ptr::pointer pointer; return x.get() > pointer(); @@ -1215,7 +893,7 @@ inline bool operator>(const unique_ptr &x, std::nullptr_t) //! Returns: x < nullptr. //! template -inline bool operator>(std::nullptr_t, const unique_ptr &x) +inline bool operator>(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr &x) { typedef typename unique_ptr::pointer pointer; return pointer() > x.get(); @@ -1224,28 +902,26 @@ inline bool operator>(std::nullptr_t, const unique_ptr &x) //! Returns: !(nullptr < x). //! template -inline bool operator<=(const unique_ptr &x, std::nullptr_t) -{ return !(nullptr < x); } +inline bool operator<=(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) +{ return !(bmd::nullptr_type() < x); } //! Returns: !(x < nullptr). //! template -inline bool operator<=(std::nullptr_t, const unique_ptr &x) -{ return !(x < nullptr); } +inline bool operator<=(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr &x) +{ return !(x < bmd::nullptr_type()); } //! Returns: !(x < nullptr). //! template -inline bool operator>=(const unique_ptr &x, std::nullptr_t) -{ return !(x < nullptr); } +inline bool operator>=(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) +{ return !(x < bmd::nullptr_type()); } //! Returns: !(nullptr < x). //! template -inline bool operator>=(std::nullptr_t, const unique_ptr &x) -{ return !(nullptr < x); } - -#endif // #if !defined(BOOST_NO_CXX11_NULLPTR) || defined(BOOST_MOVE_DOXYGEN_INVOKED) +inline bool operator>=(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr &x) +{ return !(bmd::nullptr_type() < x); } } //namespace movelib { } //namespace boost{ diff --git a/test/unique_ptr.cpp b/test/unique_ptr.cpp index c3b4811..e242406 100644 --- a/test/unique_ptr.cpp +++ b/test/unique_ptr.cpp @@ -10,8 +10,6 @@ // See http://www.boost.org/libs/move for documentation. // ////////////////////////////////////////////////////////////////////////////// -#include - #include #include #include @@ -511,17 +509,22 @@ void test() } //unique_ptr_asgn_move01 //////////////////////////////// -// unique_ptr_asgn_null +// unique_ptr_zero //////////////////////////////// -namespace unique_ptr_asgn_null { +namespace unique_ptr_zero { -// test assignment from null +// test initialization/assignment from zero void test() { //Single unique_ptr reset_counters(); { + bml::unique_ptr s2(0); + BOOST_TEST(A::count == 0); + } + BOOST_TEST(A::count == 0); + { bml::unique_ptr s2(new A); BOOST_TEST(A::count == 1); s2 = 0; @@ -532,6 +535,11 @@ void test() //Array unique_ptr { + bml::unique_ptr s2(0); + BOOST_TEST(A::count == 0); + } + BOOST_TEST(A::count == 0); + { bml::unique_ptr s2(new A[2]); BOOST_TEST(A::count == 2); s2 = 0; @@ -541,8 +549,7 @@ void test() BOOST_TEST(A::count == 0); } - -} //namespace unique_ptr_asgn_null { +} //namespace unique_ptr_zero { //////////////////////////////// @@ -1476,7 +1483,7 @@ void test() { //Single unique_ptr reset_counters(); - { + { //reset() bml::unique_ptr p(new A); BOOST_TEST(A::count == 1); A* i = p.get(); @@ -1486,7 +1493,7 @@ void test() BOOST_TEST(p.get() == 0); } BOOST_TEST(A::count == 0); - { + { //reset(p) bml::unique_ptr p(new A); BOOST_TEST(A::count == 1); A* i = p.get(); @@ -1495,9 +1502,19 @@ void test() BOOST_TEST(A::count == 1); } BOOST_TEST(A::count == 0); + { //reset(0) + bml::unique_ptr p(new A); + BOOST_TEST(A::count == 1); + A* i = p.get(); + (void)i; + p.reset(0); + BOOST_TEST(A::count == 0); + BOOST_TEST(p.get() == 0); + } + BOOST_TEST(A::count == 0); //Array unique_ptr reset_counters(); - { + { //reset() bml::unique_ptr p(new A[2]); BOOST_TEST(A::count == 2); A* i = p.get(); @@ -1507,7 +1524,7 @@ void test() BOOST_TEST(p.get() == 0); } BOOST_TEST(A::count == 0); - { + { //reset(p) bml::unique_ptr p(new A[2]); BOOST_TEST(A::count == 2); A* i = p.get(); @@ -1516,6 +1533,16 @@ void test() BOOST_TEST(A::count == 3); } BOOST_TEST(A::count == 0); + { //reset(0) + bml::unique_ptr p(new A[2]); + BOOST_TEST(A::count == 2); + A* i = p.get(); + (void)i; + p.reset(0); + BOOST_TEST(A::count == 0); + BOOST_TEST(p.get() == 0); + } + BOOST_TEST(A::count == 0); } } //namespace unique_ptr_modifiers_reset1{ @@ -1820,6 +1847,92 @@ void test() } //namespace unique_ptr_observers_op_index{ +//////////////////////////////// +// unique_ptr_nullptr +//////////////////////////////// + +namespace unique_ptr_nullptr{ + +void test() +{ + #if !defined(BOOST_NO_CXX11_NULLPTR) + //Single unique_ptr + reset_counters(); + { + bml::unique_ptr p(new A); + BOOST_TEST(A::count == 1); + A* i = p.get(); + (void)i; + p.reset(nullptr); + BOOST_TEST(A::count == 0); + BOOST_TEST(p.get() == 0); + } + BOOST_TEST(A::count == 0); + { + bml::unique_ptr p(new A); + BOOST_TEST(A::count == 1); + A* i = p.get(); + (void)i; + p = nullptr; + BOOST_TEST(A::count == 0); + BOOST_TEST(p.get() == 0); + } + BOOST_TEST(A::count == 0); + + { + bml::unique_ptr pi(nullptr); + BOOST_TEST(pi.get() == nullptr); + BOOST_TEST(pi.get() == 0); + } + BOOST_TEST(A::count == 0); + { + bml::unique_ptr pi(nullptr, bml::unique_ptr::deleter_type()); + BOOST_TEST(pi.get() == nullptr); + BOOST_TEST(pi.get() == 0); + } + BOOST_TEST(A::count == 0); + + //Array unique_ptr + reset_counters(); + { + bml::unique_ptr p(new A[2]); + BOOST_TEST(A::count == 2); + A* i = p.get(); + (void)i; + p.reset(nullptr); + BOOST_TEST(A::count == 0); + BOOST_TEST(p.get() == 0); + } + BOOST_TEST(A::count == 0); + { + bml::unique_ptr p(new A[2]); + BOOST_TEST(A::count == 2); + A* i = p.get(); + (void)i; + p = nullptr; + BOOST_TEST(A::count == 0); + BOOST_TEST(p.get() == 0); + } + BOOST_TEST(A::count == 0); + { + bml::unique_ptr pi(nullptr); + BOOST_TEST(pi.get() == nullptr); + BOOST_TEST(pi.get() == 0); + } + BOOST_TEST(A::count == 0); + { + bml::unique_ptr pi(nullptr, bml::unique_ptr::deleter_type()); + BOOST_TEST(pi.get() == nullptr); + BOOST_TEST(pi.get() == 0); + } + BOOST_TEST(A::count == 0); + + //Array element + #endif +} + +} //namespace unique_ptr_nullptr{ + //////////////////////////////// // main //////////////////////////////// @@ -1833,7 +1946,6 @@ int main() unique_ptr_asgn_move_convert02::test(); unique_ptr_asgn_move_convert03::test(); unique_ptr_asgn_move01::test(); - unique_ptr_asgn_null::test(); //Constructor unique_ptr_ctor_default01::test(); @@ -1873,8 +1985,13 @@ int main() unique_ptr_observers_op_arrow::test(); unique_ptr_observers_op_index::test(); + //nullptr + unique_ptr_zero::test(); + unique_ptr_nullptr::test(); + //Test results return boost::report_errors(); + } //Define the incomplete I type and out of line functions @@ -1902,6 +2019,3 @@ J::~J() {} void reset_counters() { A::count = 0; B::count = 0; I::count = 0; } - - -#include diff --git a/test/unique_ptr_default_deleter.cpp b/test/unique_ptr_default_deleter.cpp index a3eff8f..94103f3 100644 --- a/test/unique_ptr_default_deleter.cpp +++ b/test/unique_ptr_default_deleter.cpp @@ -10,8 +10,6 @@ // See http://www.boost.org/libs/move for documentation. // ////////////////////////////////////////////////////////////////////////////// -#include - #include #include @@ -130,5 +128,3 @@ int main() //Test results return boost::report_errors(); } - -#include diff --git a/test/unique_ptr_functions.cpp b/test/unique_ptr_functions.cpp index dfc3f73..d730809 100644 --- a/test/unique_ptr_functions.cpp +++ b/test/unique_ptr_functions.cpp @@ -9,7 +9,6 @@ // See http://www.boost.org/libs/move for documentation. // ////////////////////////////////////////////////////////////////////////////// -#include #include #include @@ -135,30 +134,135 @@ void test() //Equal BOOST_TEST(rpl == rpl && rpl.get() == rpl.get()); - BOOST_TEST(!(rpl == rpg) && !(rpl.get() != rpg.get())); + BOOST_TEST(!(rpl == rpg) && !(rpl.get() == rpg.get())); //Unequal BOOST_TEST(rpl != rpg && rpl.get() != rpg.get()); BOOST_TEST(!(rpl != rpl) && !(rpl.get() != rpl.get())); //Less BOOST_TEST(rpl < rpg && rpl.get() < rpg.get()); - BOOST_TEST(!(rpl < rpg) && !(rpl.get() < rpg.get())); + BOOST_TEST(!(rpg < rpl) && !(rpg.get() < rpl.get())); //Greater BOOST_TEST(rpg > rpl && rpg.get() > rpl.get()); - BOOST_TEST(!(rpg > rpg) && !(rpg.get() > rpl.get())); + BOOST_TEST(!(rpg > rpg) && !(rpg.get() > rpg.get())); //Less or equal BOOST_TEST(rpl <= rpg && rpl.get() <= rpg.get()); BOOST_TEST(rpl <= rpl && rpl.get() <= rpl.get()); - BOOST_TEST(!(rpg <= rpl) && !(rpg.get() < rpl.get())); + BOOST_TEST(!(rpg <= rpl) && !(rpg.get() <= rpl.get())); //Greater or equal BOOST_TEST(rpg >= rpl && rpg.get() >= rpl.get()); BOOST_TEST(rpg >= rpg && rpg.get() >= rpg.get()); - BOOST_TEST(!(rpl >= rpg) && !(rpl.get() < rpg.get())); + BOOST_TEST(!(rpl >= rpg) && !(rpl.get() >= rpg.get())); } BOOST_TEST(A::count == 0); } } //namespace unique_compare{ + +//////////////////////////////// +// unique_compare_zero +//////////////////////////////// +namespace unique_compare_zero{ + +void test() +{ + //Single element deleter + reset_counters(); + { + bml::unique_ptr pa(bml::make_unique()); + bml::unique_ptr pb; + BOOST_TEST(A::count == 1); + + //Equal + BOOST_TEST(!(pa == 0)); + BOOST_TEST(!(0 == pa)); + BOOST_TEST((pb == 0)); + BOOST_TEST((0 == pb)); + //Unequal + BOOST_TEST((pa != 0)); + BOOST_TEST((0 != pa)); + BOOST_TEST(!(pb != 0)); + BOOST_TEST(!(0 != pb)); + //Less + BOOST_TEST((pa < 0) == (pa.get() < 0)); + BOOST_TEST((0 < pa) == (0 < pa.get())); + BOOST_TEST((pb < 0) == (pb.get() < 0)); + BOOST_TEST((0 < pb) == (0 < pb.get())); + //Greater + BOOST_TEST((pa > 0) == (pa.get() > 0)); + BOOST_TEST((0 > pa) == (0 > pa.get())); + BOOST_TEST((pb > 0) == (pb.get() > 0)); + BOOST_TEST((0 > pb) == (0 > pb.get())); + //Less or equal + BOOST_TEST((pa <= 0) == (pa.get() <= 0)); + BOOST_TEST((0 <= pa) == (0 <= pa.get())); + BOOST_TEST((pb <= 0) == (pb.get() <= 0)); + BOOST_TEST((0 <= pb) == (0 <= pb.get())); + //Greater or equal + BOOST_TEST((pa >= 0) == (pa.get() >= 0)); + BOOST_TEST((0 >= pa) == (0 >= pa.get())); + BOOST_TEST((pb >= 0) == (pb.get() >= 0)); + BOOST_TEST((0 >= pb) == (0 >= pb.get())); + } + BOOST_TEST(A::count == 0); +} + +} //namespace unique_compare_zero{ + +//////////////////////////////// +// unique_compare_nullptr +//////////////////////////////// + +namespace unique_compare_nullptr{ + +void test() +{ + #if !defined(BOOST_NO_CXX11_NULLPTR) + //Single element deleter + reset_counters(); + { + bml::unique_ptr pa(bml::make_unique()); + bml::unique_ptr pb; + BOOST_TEST(A::count == 1); + + //Equal + BOOST_TEST(!(pa == nullptr)); + BOOST_TEST(!(nullptr == pa)); + BOOST_TEST((pb == nullptr)); + BOOST_TEST((nullptr == pb)); + //Unequal + BOOST_TEST((pa != nullptr)); + BOOST_TEST((nullptr != pa)); + BOOST_TEST(!(pb != nullptr)); + BOOST_TEST(!(nullptr != pb)); + //Less + BOOST_TEST((pa < nullptr) == (pa.get() < nullptr)); + BOOST_TEST((nullptr < pa) == (nullptr < pa.get())); + BOOST_TEST((pb < nullptr) == (pb.get() < nullptr)); + BOOST_TEST((nullptr < pb) == (nullptr < pb.get())); + //Greater + BOOST_TEST((pa > nullptr) == (pa.get() > nullptr)); + BOOST_TEST((nullptr > pa) == (nullptr > pa.get())); + BOOST_TEST((pb > nullptr) == (pb.get() > nullptr)); + BOOST_TEST((nullptr > pb) == (nullptr > pb.get())); + //Less or equal + BOOST_TEST((pa <= nullptr) == (pa.get() <= nullptr)); + BOOST_TEST((nullptr <= pa) == (nullptr <= pa.get())); + BOOST_TEST((pb <= nullptr) == (pb.get() <= nullptr)); + BOOST_TEST((nullptr <= pb) == (nullptr <= pb.get())); + //Greater or equal + BOOST_TEST((pa >= nullptr) == (pa.get() >= nullptr)); + BOOST_TEST((nullptr >= pa) == (nullptr >= pa.get())); + BOOST_TEST((pb >= nullptr) == (pb.get() >= nullptr)); + BOOST_TEST((nullptr >= pb) == (nullptr >= pb.get())); + } + BOOST_TEST(A::count == 0); + #endif //#if !defined(BOOST_NO_CXX11_NULLPTR) +} + +} //namespace unique_compare_nullptr{ + + //////////////////////////////// // main //////////////////////////////// @@ -166,9 +270,10 @@ int main() { make_unique_single::test(); make_unique_array::test(); + unique_compare::test(); + unique_compare_zero::test(); + unique_compare_nullptr::test(); //Test results return boost::report_errors(); } - -#include From 738e360f403353a0768c952d59999cab2e438e3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Fri, 29 Aug 2014 10:28:09 +0200 Subject: [PATCH 03/10] Improved move-only deleters in C++03, now they can be caught as rvalues. --- include/boost/move/unique_ptr.hpp | 171 ++++++++++++++++-------------- test/unique_ptr.cpp | 148 ++++++++++---------------- 2 files changed, 146 insertions(+), 173 deletions(-) diff --git a/include/boost/move/unique_ptr.hpp b/include/boost/move/unique_ptr.hpp index f9b4128..f86ffc3 100644 --- a/include/boost/move/unique_ptr.hpp +++ b/include/boost/move/unique_ptr.hpp @@ -41,17 +41,37 @@ namespace boost{ namespace move_detail { +//////////////////////////////////////////// +// deleter types +//////////////////////////////////////////// +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +template +class is_noncopyable +{ + typedef char true_t; + class false_t { char dummy[2]; }; + template static false_t dispatch(...); + template static true_t dispatch(typename U::boost_move_no_copy_constructor_or_assign*); + public: + static const bool value = sizeof(dispatch(0)) == sizeof(true_t); +}; +#endif //defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template struct deleter_types { typedef typename add_lvalue_reference::type del_ref; typedef typename add_const_lvalue_reference::type del_cref; + #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES typedef typename if_c < is_lvalue_reference::value, D, del_cref >::type deleter_arg_type1; - #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - typedef typename remove_reference::type && deleter_arg_type2; + typedef typename remove_reference::type && deleter_arg_type2; #else - typedef ::boost::rv &deleter_arg_type2; + typedef typename if_c + < is_noncopyable::value, nat, del_cref>::type non_ref_deleter_arg1; + typedef typename if_c< is_lvalue_reference::value + , D, non_ref_deleter_arg1 >::type deleter_arg_type1; + typedef ::boost::rv & deleter_arg_type2; #endif }; @@ -61,10 +81,9 @@ struct deleter_types template ::value || is_reference::value > struct unique_ptr_data { - typedef typename deleter_types::deleter_arg_type1 deleter_arg_type1; - typedef typename deleter_types::deleter_arg_type2 deleter_arg_type2; - typedef typename deleter_types::del_ref del_ref; - typedef typename deleter_types::del_cref del_cref; + typedef typename deleter_types::deleter_arg_type1 deleter_arg_type1; + typedef typename deleter_types::del_ref del_ref; + typedef typename deleter_types::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 unique_ptr_data(P p, BOOST_FWD_REF(U) d) BOOST_NOEXCEPT - : m_p(::boost::forward(p)), d(::boost::forward(d)) + : m_p(p), d(::boost::forward(d)) {} del_ref deleter() { return d; } @@ -102,16 +117,15 @@ template struct unique_ptr_data : private D { - typedef typename deleter_types::deleter_arg_type1 deleter_arg_type1; - typedef typename deleter_types::deleter_arg_type2 deleter_arg_type2; - typedef typename deleter_types::del_ref del_ref; - typedef typename deleter_types::del_cref del_cref; + typedef typename deleter_types::deleter_arg_type1 deleter_arg_type1; + typedef typename deleter_types::del_ref del_ref; + typedef typename deleter_types::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 : D(d1), m_p(p) {} - unique_ptr_data(P p, deleter_arg_type2 d2) BOOST_NOEXCEPT - : D(::boost::move(d2)), m_p(p) - {} - template unique_ptr_data(P p, BOOST_FWD_REF(U) d) BOOST_NOEXCEPT : D(::boost::forward(d)), m_p(p) {} - del_ref deleter() { return static_cast(*this); } - del_cref deleter() const{ return static_cast(*this); } + del_ref deleter() BOOST_NOEXCEPT { return static_cast(*this); } + del_cref deleter() const BOOST_NOEXCEPT { return static_cast(*this); } P m_p; @@ -445,11 +455,8 @@ class unique_ptr typedef move_detail::pointer_type pointer_type_obtainer; typedef bmd::unique_ptr_data 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 - >::value > is_default_deleter_t; + typedef typename bmd::deleter_types::deleter_arg_type1 deleter_arg_type1; + typedef typename bmd::deleter_types::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 unique_ptr(pointer p, A& d). //! - If D is an lvalue-reference type const A&, then the signature is unique_ptr(pointer p, const A& d). //! + //! + //! Requires: 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. + //! //! Effects: Constructs a unique_ptr object which owns p, initializing the stored pointer with p and //! initializing the deleter as described above. //! - //! Postconditions: get() == p.get_deleter() returns a reference to the stored deleter. If D is a + //! Postconditions: get() == p. get_deleter() returns a reference to the stored deleter. If D is a //! reference type then get_deleter() returns a reference to the lvalue d. //! //! Remarks: This constructor shall not participate in overload resolution unless: @@ -539,6 +554,8 @@ class unique_ptr : m_data(p, d1) {} + //! Effects: Same effects as template unique_ptr(Pointer p, deleter_arg_type1 d1) + //! and additionally get() == nullptr 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 unique_ptr(pointer p, A&& d). //! - If D is an lvalue-reference type const A&, then the signature is unique_ptr(pointer p, const A&& d). //! + //! Requires: 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. + //! //! Effects: Constructs a unique_ptr object which owns p, initializing the stored pointer with p and //! initializing the deleter as described above. //! - //! Postconditions: get() == p.get_deleter() returns a reference to the stored deleter. If D is a + //! Postconditions: get() == p. get_deleter() returns a reference to the stored deleter. If D is a //! reference type then get_deleter() returns a reference to the lvalue d. //! //! Remarks: This constructor shall not participate in overload resolution unless: @@ -564,6 +587,8 @@ class unique_ptr : m_data(p, ::boost::move(d2)) {} + //! Effects: Same effects as template unique_ptr(Pointer p, deleter_arg_type2 d2) + //! and additionally get() == nullptr 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 //! //! Returns: *this. unique_ptr& operator=(BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) BOOST_NOEXCEPT - { - this->reset(); - return *this; - } + { this->reset(); return *this; } //! Requires: get() != nullptr. //! @@ -668,7 +690,7 @@ class unique_ptr //! //! Remarks::type) - operator*() const + operator*() const BOOST_NOEXCEPT { BOOST_STATIC_ASSERT((!bmd::is_array::value)); return *get(); @@ -680,7 +702,7 @@ class unique_ptr //! //! Remarks::type) - operator[](size_t i) const + operator[](size_t i) const BOOST_NOEXCEPT { BOOST_STATIC_ASSERT((bmd::is_array::value)); const pointer p = this->get(); @@ -698,7 +720,9 @@ class unique_ptr pointer operator->() const BOOST_NOEXCEPT { BOOST_STATIC_ASSERT((!bmd::is_array::value)); - return get(); + const pointer p = this->get(); + BOOST_ASSERT(p); + return p; } //! Returns: The stored pointer. @@ -732,7 +756,6 @@ class unique_ptr : bmd::explicit_bool_arg(0); } - //! Postcondition: get() == nullptr. //! //! Returns: The value get() had at the start of the call to release. @@ -839,88 +862,76 @@ inline bool operator>=(const unique_ptr &x, const unique_ptr &y) //! Returns:!x. //! -template -inline bool operator==(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) BOOST_NOEXCEPT +template +inline bool operator==(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) BOOST_NOEXCEPT { return !x; } //! Returns:!x. //! -template -inline bool operator==(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr &x) BOOST_NOEXCEPT +template +inline bool operator==(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr &x) BOOST_NOEXCEPT { return !x; } //! Returns: (bool)x. //! -template -inline bool operator!=(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) BOOST_NOEXCEPT +template +inline bool operator!=(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) BOOST_NOEXCEPT { return !!x; } //! Returns: (bool)x. //! -template -inline bool operator!=(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr &x) BOOST_NOEXCEPT +template +inline bool operator!=(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr &x) BOOST_NOEXCEPT { return !!x; } -//! Requires: operator shall induce a strict weak ordering on unique_ptr::pointer values. +//! Requires: operator shall induce a strict weak ordering on unique_ptr::pointer values. //! //! Returns: Returns x.get() < pointer(). -template -inline bool operator<(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) -{ - typedef typename unique_ptr::pointer pointer; - return x.get() < pointer(); -} +template +inline bool operator<(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) +{ return x.get() < unique_ptr::pointer(); } -//! Requires: operator shall induce a strict weak ordering on unique_ptr::pointer values. +//! Requires: operator shall induce a strict weak ordering on unique_ptr::pointer values. //! //! Returns: Returns pointer() < x.get(). -template -inline bool operator<(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr &x) -{ - typedef typename unique_ptr::pointer pointer; - return pointer() < x.get(); -} +template +inline bool operator<(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr &x) +{ return unique_ptr::pointer() < x.get(); } //! Returns: nullptr < x. //! -template -inline bool operator>(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) -{ - typedef typename unique_ptr::pointer pointer; - return x.get() > pointer(); -} +template +inline bool operator>(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) +{ return x.get() > unique_ptr::pointer(); } //! Returns: x < nullptr. //! -template -inline bool operator>(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr &x) -{ - typedef typename unique_ptr::pointer pointer; - return pointer() > x.get(); -} +template +inline bool operator>(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr &x) +{ return unique_ptr::pointer() > x.get(); } //! Returns: !(nullptr < x). //! -template -inline bool operator<=(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) +template +inline bool operator<=(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) { return !(bmd::nullptr_type() < x); } //! Returns: !(x < nullptr). //! -template -inline bool operator<=(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr &x) +template +inline bool operator<=(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr &x) { return !(x < bmd::nullptr_type()); } //! Returns: !(x < nullptr). //! -template -inline bool operator>=(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) +template +inline bool operator>=(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) { return !(x < bmd::nullptr_type()); } //! Returns: !(nullptr < x). //! -template -inline bool operator>=(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr &x) +template +inline bool operator>=(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr &x) { return !(bmd::nullptr_type() < x); } } //namespace movelib { diff --git a/test/unique_ptr.cpp b/test/unique_ptr.cpp index e242406..e52a43d 100644 --- a/test/unique_ptr.cpp +++ b/test/unique_ptr.cpp @@ -58,22 +58,6 @@ class def_constr_deleter { ++state_; is_array ? delete []p : delete p; } }; -template -struct enable_if_conversion_acceptable - : ::boost::move_detail::enable_if_c - < OtherIsArray && ::boost::move_detail::is_same_cvelement_and_convertible::value - , Type - > -{}; - -template -struct enable_if_conversion_acceptable - : ::boost::move_detail::enable_if_c - < !OtherIsArray && ::boost::move_detail::is_convertible::value - , Type - > -{}; - //A deleter that can be copy constructed template class copy_constr_deleter @@ -88,24 +72,13 @@ class copy_constr_deleter template copy_constr_deleter(const copy_constr_deleter& - , typename enable_if_conversion_acceptable - < copy_constr_deleter::is_array - , is_array - , typename copy_constr_deleter::element_type - , element_type - >::type* = 0) + , typename boost::move_detail::enable_def_del::type* =0) { state_ = 5; } explicit copy_constr_deleter(int s) : state_(s) {} template - typename enable_if_conversion_acceptable - < copy_constr_deleter::is_array - , is_array - , typename copy_constr_deleter::element_type - , element_type - , copy_constr_deleter& - >::type + typename boost::move_detail::enable_def_del::type operator=(const copy_constr_deleter &d) { state_ = d.state(); @@ -145,12 +118,7 @@ class move_constr_deleter template move_constr_deleter(BOOST_RV_REF(move_constr_deleter) d - , typename enable_if_conversion_acceptable - < move_constr_deleter::is_array - , is_array - , typename move_constr_deleter::element_type - , element_type - >::type* = 0) + , typename boost::move_detail::enable_def_del::type* =0) : state_(d.state()) { d.set_state(0); } @@ -162,13 +130,7 @@ class move_constr_deleter } template - typename enable_if_conversion_acceptable - < move_constr_deleter::is_array - , is_array - , typename move_constr_deleter::element_type - , element_type - , move_constr_deleter& - >::type + typename boost::move_detail::enable_def_del::type operator=(BOOST_RV_REF(move_constr_deleter) d) { state_ = d.state(); @@ -318,7 +280,6 @@ void test() } //namespace unique_ptr_asgn_move_convert01{ - //////////////////////////////// // unique_ptr_asgn_move_convert02 //////////////////////////////// @@ -362,8 +323,6 @@ void test() BOOST_TEST(A::count == 0); } - - } //namespace unique_ptr_asgn_move_convert02{ //////////////////////////////// @@ -508,50 +467,6 @@ void test() } //unique_ptr_asgn_move01 -//////////////////////////////// -// unique_ptr_zero -//////////////////////////////// -namespace unique_ptr_zero { - -// test initialization/assignment from zero - -void test() -{ - //Single unique_ptr - reset_counters(); - { - bml::unique_ptr s2(0); - BOOST_TEST(A::count == 0); - } - BOOST_TEST(A::count == 0); - { - bml::unique_ptr s2(new A); - BOOST_TEST(A::count == 1); - s2 = 0; - BOOST_TEST(A::count == 0); - BOOST_TEST(s2.get() == 0); - } - BOOST_TEST(A::count == 0); - - //Array unique_ptr - { - bml::unique_ptr s2(0); - BOOST_TEST(A::count == 0); - } - BOOST_TEST(A::count == 0); - { - bml::unique_ptr s2(new A[2]); - BOOST_TEST(A::count == 2); - s2 = 0; - BOOST_TEST(A::count == 0); - BOOST_TEST(s2.get() == 0); - } - BOOST_TEST(A::count == 0); -} - -} //namespace unique_ptr_zero { - - //////////////////////////////// // unique_ptr_ctor_default01 //////////////////////////////// @@ -710,7 +625,6 @@ void test() BOOST_TEST(B::count == 0); } - } //namespace unique_ptr_ctor_move_convert02{ //////////////////////////////// @@ -801,8 +715,6 @@ void test() } //namespace unique_ptr_ctor_move_convert04{ - - //////////////////////////////// // unique_ptr_ctor_move_convert05 //////////////////////////////// @@ -1072,6 +984,9 @@ void test() bml::unique_ptr > s(p, ::boost::move(d)); BOOST_TEST(s.get() == p); BOOST_TEST(s.get_deleter().state() == 5); + bml::unique_ptr > s2(s.release(), move_constr_deleter(6)); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s2.get_deleter().state() == 6); } BOOST_TEST(A::count == 0); //Array unique_ptr @@ -1083,6 +998,9 @@ void test() bml::unique_ptr > s(p, ::boost::move(d)); BOOST_TEST(s.get() == p); BOOST_TEST(s.get_deleter().state() == 5); + bml::unique_ptr > s2(s.release(), move_constr_deleter(6)); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s2.get_deleter().state() == 6); } BOOST_TEST(A::count == 0); } @@ -1847,6 +1765,50 @@ void test() } //namespace unique_ptr_observers_op_index{ +//////////////////////////////// +// unique_ptr_zero +//////////////////////////////// +namespace unique_ptr_zero { + +// test initialization/assignment from zero + +void test() +{ + //Single unique_ptr + reset_counters(); + { + bml::unique_ptr s2(0); + BOOST_TEST(A::count == 0); + } + BOOST_TEST(A::count == 0); + { + bml::unique_ptr s2(new A); + BOOST_TEST(A::count == 1); + s2 = 0; + BOOST_TEST(A::count == 0); + BOOST_TEST(s2.get() == 0); + } + BOOST_TEST(A::count == 0); + + //Array unique_ptr + { + bml::unique_ptr s2(0); + BOOST_TEST(A::count == 0); + } + BOOST_TEST(A::count == 0); + { + bml::unique_ptr s2(new A[2]); + BOOST_TEST(A::count == 2); + s2 = 0; + BOOST_TEST(A::count == 0); + BOOST_TEST(s2.get() == 0); + } + BOOST_TEST(A::count == 0); +} + +} //namespace unique_ptr_zero { + + //////////////////////////////// // unique_ptr_nullptr //////////////////////////////// @@ -1939,7 +1901,7 @@ void test() int main() { //General - pointer_type::test(); + pointer_type::test(); //Assignment unique_ptr_asgn_move_convert01::test(); From 085a814cf209f265fce3f09eef90ac46e6bddd97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Fri, 29 Aug 2014 11:29:26 +0200 Subject: [PATCH 04/10] Added missing typenames --- include/boost/move/unique_ptr.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/move/unique_ptr.hpp b/include/boost/move/unique_ptr.hpp index f86ffc3..3cfb36e 100644 --- a/include/boost/move/unique_ptr.hpp +++ b/include/boost/move/unique_ptr.hpp @@ -889,26 +889,26 @@ inline bool operator!=(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptrReturns: Returns x.get() < pointer(). template inline bool operator<(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) -{ return x.get() < unique_ptr::pointer(); } +{ return x.get() < typename unique_ptr::pointer(); } //! Requires: operator shall induce a strict weak ordering on unique_ptr::pointer values. //! //! Returns: Returns pointer() < x.get(). template inline bool operator<(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr &x) -{ return unique_ptr::pointer() < x.get(); } +{ return typename unique_ptr::pointer() < x.get(); } //! Returns: nullptr < x. //! template inline bool operator>(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) -{ return x.get() > unique_ptr::pointer(); } +{ return x.get() > typename unique_ptr::pointer(); } //! Returns: x < nullptr. //! template inline bool operator>(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr &x) -{ return unique_ptr::pointer() > x.get(); } +{ return typename unique_ptr::pointer() > x.get(); } //! Returns: !(nullptr < x). //! From 583378a946cf6a5dde1411b6285ec6a0a1adfb3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sat, 30 Aug 2014 02:43:42 +0200 Subject: [PATCH 05/10] Update boost::move documentation with a more accurate description. --- include/boost/move/utility_core.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/boost/move/utility_core.hpp b/include/boost/move/utility_core.hpp index 1786b1e..3e04172 100644 --- a/include/boost/move/utility_core.hpp +++ b/include/boost/move/utility_core.hpp @@ -164,8 +164,9 @@ #if defined(BOOST_MOVE_DOXYGEN_INVOKED) //! This function provides a way to convert a reference into a rvalue reference - //! in compilers with rvalue references. For other compilers converts T & into - //! ::boost::rv & so that move emulation is activated. + //! in compilers with rvalue references. For other compilers if `T` is Boost.Move + //! enabled type then it converts `T&` into ::boost::rv & so that + //! move emulation is activated, else it returns `T &`. template rvalue_reference move(input_reference) noexcept; From 19d35253cf1d058a3b149e4af023d7a3dc953cef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Mon, 1 Sep 2014 23:59:10 +0200 Subject: [PATCH 06/10] Added support for bounded arrays in unique_ptr. Splitted test in several subtests. --- include/boost/move/detail/meta_utils.hpp | 34 + include/boost/move/make_unique.hpp | 56 +- include/boost/move/unique_ptr.hpp | 83 +- proj/vc7ide/Move.sln | 62 +- proj/vc7ide/unique_ptr_assign_test.vcproj | 135 ++ proj/vc7ide/unique_ptr_ctordtor_test.vcproj | 135 ++ proj/vc7ide/unique_ptr_modifiers_test.vcproj | 135 ++ proj/vc7ide/unique_ptr_movector_test.vcproj | 135 ++ proj/vc7ide/unique_ptr_nullptr_test.vcproj | 135 ++ proj/vc7ide/unique_ptr_observers_test.vcproj | 134 ++ ...st.vcproj => unique_ptr_types_test.vcproj} | 18 +- test/unique_ptr.cpp | 1983 ----------------- test/unique_ptr_assign.cpp | 444 ++++ test/unique_ptr_ctordtor.cpp | 708 ++++++ test/unique_ptr_default_deleter.cpp | 74 + test/unique_ptr_functions.cpp | 38 +- test/unique_ptr_modifiers.cpp | 377 ++++ test/unique_ptr_movector.cpp | 516 +++++ test/unique_ptr_nullptr.cpp | 228 ++ test/unique_ptr_observers.cpp | 287 +++ test/unique_ptr_test_utils_beg.hpp | 209 ++ test/unique_ptr_test_utils_end.hpp | 46 + test/unique_ptr_types.cpp | 164 ++ 23 files changed, 4091 insertions(+), 2045 deletions(-) create mode 100644 proj/vc7ide/unique_ptr_assign_test.vcproj create mode 100644 proj/vc7ide/unique_ptr_ctordtor_test.vcproj create mode 100644 proj/vc7ide/unique_ptr_modifiers_test.vcproj create mode 100644 proj/vc7ide/unique_ptr_movector_test.vcproj create mode 100644 proj/vc7ide/unique_ptr_nullptr_test.vcproj create mode 100644 proj/vc7ide/unique_ptr_observers_test.vcproj rename proj/vc7ide/{unique_ptr_test.vcproj => unique_ptr_types_test.vcproj} (86%) delete mode 100644 test/unique_ptr.cpp create mode 100644 test/unique_ptr_assign.cpp create mode 100644 test/unique_ptr_ctordtor.cpp create mode 100644 test/unique_ptr_modifiers.cpp create mode 100644 test/unique_ptr_movector.cpp create mode 100644 test/unique_ptr_nullptr.cpp create mode 100644 test/unique_ptr_observers.cpp create mode 100644 test/unique_ptr_test_utils_beg.hpp create mode 100644 test/unique_ptr_test_utils_end.hpp create mode 100644 test/unique_ptr_types.cpp diff --git a/include/boost/move/detail/meta_utils.hpp b/include/boost/move/detail/meta_utils.hpp index 6cc1763..61d37a9 100644 --- a/include/boost/move/detail/meta_utils.hpp +++ b/include/boost/move/detail/meta_utils.hpp @@ -264,6 +264,40 @@ struct remove_extent typedef T type; }; +////////////////////////////////////// +// extent +////////////////////////////////////// + +template +struct extent +{ + static const std::size_t value = 0; +}; + +template +struct extent +{ + static const std::size_t value = 0; +}; + +template +struct extent +{ + static const std::size_t value = extent::value; +}; + +template +struct extent +{ + static const std::size_t value = N; +}; + +template +struct extent +{ + static const std::size_t value = extent::value; +}; + ////////////////////////////////////// // element_pointer ////////////////////////////////////// diff --git a/include/boost/move/make_unique.hpp b/include/boost/move/make_unique.hpp index 825a66a..23b8555 100644 --- a/include/boost/move/make_unique.hpp +++ b/include/boost/move/make_unique.hpp @@ -71,13 +71,9 @@ namespace movelib { //! //! Returns: unique_ptr(new T(std::forward(args)...)). template -inline - #if defined(BOOST_MOVE_DOXYGEN_INVOKED) - unique_ptr - #else - typename ::boost::move_detail::unique_ptr_if::t_is_not_array - #endif - make_unique(BOOST_FWD_REF(Args)... args) +inline BOOST_MOVE_DOC1ST(unique_ptr, + typename ::boost::move_detail::unique_ptr_if::t_is_not_array) + make_unique(BOOST_FWD_REF(Args)... args) { return unique_ptr(new T(::boost::forward(args)...)); } #else @@ -109,35 +105,51 @@ inline #endif +//! Remarks: This function shall not participate in overload resolution unless T is not an array. +//! +//! Returns: unique_ptr(new T) (default initialization) +template +inline BOOST_MOVE_DOC1ST(unique_ptr, + typename ::boost::move_detail::unique_ptr_if::t_is_not_array) + make_unique_definit() +{ + return unique_ptr(new T); +} //! Remarks: This function shall not participate in overload resolution unless T is an array of //! unknown bound. //! -//! Returns: unique_ptr(new remove_extent_t[n]()). +//! Returns: unique_ptr(new remove_extent_t[n]()) (value initialization) template -inline - #if defined(BOOST_MOVE_DOXYGEN_INVOKED) - unique_ptr - #else - typename ::boost::move_detail::unique_ptr_if::t_is_array_of_unknown_bound - #endif - make_unique(std::size_t n) +inline BOOST_MOVE_DOC1ST(unique_ptr, + typename ::boost::move_detail::unique_ptr_if::t_is_array_of_unknown_bound) + make_unique(std::size_t n) { typedef typename ::boost::move_detail::remove_extent::type U; return unique_ptr(new U[n]()); } -#if defined(BOOST_MOVE_DOXYGEN_INVOKED) || !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) +//! Remarks: This function shall not participate in overload resolution unless T is an array of +//! unknown bound. +//! +//! Returns: unique_ptr(new remove_extent_t[n]) (default initialization) +template +inline BOOST_MOVE_DOC1ST(unique_ptr, + typename ::boost::move_detail::unique_ptr_if::t_is_array_of_unknown_bound) + make_unique_definit(std::size_t n) +{ + typedef typename ::boost::move_detail::remove_extent::type U; + return unique_ptr(new U[n]); +} + +#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) //! Remarks: This function shall not participate in overload resolution unless T is //! an array of known bound. template - #if defined(BOOST_MOVE_DOXYGEN_INVOKED) - unspecified - #else - typename ::boost::move_detail::unique_ptr_if::t_is_array_of_known_bound - #endif - make_unique(BOOST_FWD_REF(Args) ...) = delete; +inline BOOST_MOVE_DOC1ST(unspecified, + typename ::boost::move_detail::unique_ptr_if::t_is_array_of_known_bound) + make_unique(BOOST_FWD_REF(Args) ...) = delete; #endif } //namespace movelib { diff --git a/include/boost/move/unique_ptr.hpp b/include/boost/move/unique_ptr.hpp index 3cfb36e..5544d55 100644 --- a/include/boost/move/unique_ptr.hpp +++ b/include/boost/move/unique_ptr.hpp @@ -18,9 +18,7 @@ #include #include -#if !defined(BOOST_NO_CXX11_NULLPTR) -#include //For std::nullptr_t -#endif +#include //For std::nullptr_t and std::size_t //!\file //! Describes the smart pointer unique_ptr, a drop-in replacement for std::unique_ptr, @@ -197,17 +195,37 @@ struct is_unique_ptr_convertible {}; //////////////////////////////////////// -//// enable_def_del / enable_defdel_call +//// enable_def_del //////////////////////////////////////// +//compatible with a pointer type T*: +//When either Y* is convertible to T* +//Y is U[N] and T is U cv [] +template +struct def_del_compatible_cond +{ + static const bool value = is_convertible::value; +}; + +template +struct def_del_compatible_cond +{ + static const bool value = def_del_compatible_cond::value; +}; + template struct enable_def_del - : enable_if_c - < (is_array::value == is_array::value) && is_unique_ptr_convertible - ::value, typename remove_extent::type*, typename remove_extent::type*>::value - , Type> + : enable_if_c::value, Type> {}; +//////////////////////////////////////// +//// enable_defdel_call +//////////////////////////////////////// + +//When 2nd is T[N], 1st(*)[N] shall be convertible to T[N]*; +//When 2nd is T[], 1st(*)[] shall be convertible to T[]*; +//Otherwise, 1st* shall be convertible to 2nd*. + template struct enable_defdel_call : public enable_def_del @@ -218,6 +236,11 @@ struct enable_defdel_call : public enable_def_del {}; +template +struct enable_defdel_call + : public enable_def_del +{}; + //////////////////////////////////////// //// enable_up_moveconv_assign //////////////////////////////////////// @@ -234,17 +257,28 @@ struct enable_up_ptr template struct unique_moveconvert_assignable { - static const bool value = !is_array::value && is_unique_ptr_convertible - ::type, typename pointer_type::type>::value; + static const bool value = (extent::value == extent::value)&& is_unique_ptr_convertible + ::value, typename pointer_type::type, typename pointer_type::type>::value; }; -template -struct unique_moveconvert_assignable +template +struct unique_moveconvert_assignable { - static const bool value = is_array::value && is_unique_ptr_convertible - ::type, typename pointer_type::type>::value; + static const bool value = unique_moveconvert_assignable::value; +}; +/* +template +struct unique_moveconvert_assignable +{ + static const bool value = unique_moveconvert_assignable::value; }; +template +struct unique_moveconvert_assignable +{ + static const bool value = (M == N) && unique_moveconvert_assignable::value; +}; +*/ template struct enable_up_moveconv_assign : enable_if_c::value, Type> @@ -394,6 +428,11 @@ struct default_delete element_type * const p = static_cast(ptr); bmd::is_array::value ? delete [] p : delete p; } + + //! Effects: Same as (*this)(static_cast(nullptr)). + //! + void operator()(BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) const BOOST_NOEXCEPT + { BOOST_STATIC_ASSERT(sizeof(element_type) > 0); } }; @@ -693,7 +732,7 @@ class unique_ptr operator*() const BOOST_NOEXCEPT { BOOST_STATIC_ASSERT((!bmd::is_array::value)); - return *get(); + return *m_data.m_p; } //! Requires: i < the number of elements in the array to which the stored pointer points. @@ -702,12 +741,11 @@ class unique_ptr //! //! Remarks::type) - operator[](size_t i) const BOOST_NOEXCEPT + operator[](std::size_t i) const BOOST_NOEXCEPT { - BOOST_STATIC_ASSERT((bmd::is_array::value)); - const pointer p = this->get(); - BOOST_ASSERT(p); - return p[i]; + BOOST_ASSERT( bmd::extent::value == 0 || i < bmd::extent::value ); + BOOST_ASSERT(m_data.m_p); + return m_data.m_p[i]; } //! Requires: get() != nullptr. @@ -720,9 +758,8 @@ class unique_ptr pointer operator->() const BOOST_NOEXCEPT { BOOST_STATIC_ASSERT((!bmd::is_array::value)); - const pointer p = this->get(); - BOOST_ASSERT(p); - return p; + BOOST_ASSERT(m_data.m_p); + return m_data.m_p; } //! Returns: The stored pointer. diff --git a/proj/vc7ide/Move.sln b/proj/vc7ide/Move.sln index 32eb5bb..e9d250b 100644 --- a/proj/vc7ide/Move.sln +++ b/proj/vc7ide/Move.sln @@ -71,11 +71,35 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unique_ptr_default_deleter_ ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unique_ptr_test", "unique_ptr_test.vcproj", "{C57C28A3-4FE0-6208-BF87-A2B61D3A7671}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unique_ptr_functions_test", "unique_ptr_functions.vcproj", "{C57C25A3-4620-FE08-F8B7-AB673D762B60}" ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unique_ptr_functions_test", "unique_ptr_functions.vcproj", "{C57C25A3-4620-FE08-F8B7-AB673D762B60}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unique_ptr_assign_test", "unique_ptr_assign_test.vcproj", "{C57C28A3-4FE0-6208-BF87-B2B61D3A7674}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unique_ptr_ctordtor_test", "unique_ptr_ctordtor_test.vcproj", "{C57C28A3-4FE0-6208-BF87-B2B61D3A7676}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unique_ptr_modifiers_test", "unique_ptr_modifiers_test.vcproj", "{C57C28A3-4FE0-6208-BF87-B2B61D3A7673}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unique_ptr_movector_test", "unique_ptr_movector_test.vcproj", "{C57C28A3-4FE0-6208-BF87-B2B61D3A7672}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unique_ptr_nullptr_test", "unique_ptr_nullptr_test.vcproj", "{C57C28A3-4FE0-6208-BF87-B2B61D3A7671}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unique_ptr_test", "unique_ptr_observers_test.vcproj", "{C57C28A3-4FE0-6208-BF87-B2B61D3A7670}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unique_ptr_types_test", "unique_ptr_types_test.vcproj", "{C57C28A3-4FE0-6208-BF87-B2B61D3A7675}" ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject @@ -159,14 +183,38 @@ Global {C57C25A3-4620-FE08-F8B7-AB673D762B60}.Debug.Build.0 = Debug|Win32 {C57C25A3-4620-FE08-F8B7-AB673D762B60}.Release.ActiveCfg = Release|Win32 {C57C25A3-4620-FE08-F8B7-AB673D762B60}.Release.Build.0 = Release|Win32 - {C57C28A3-4FE0-6208-BF87-A2B61D3A7671}.Debug.ActiveCfg = Debug|Win32 - {C57C28A3-4FE0-6208-BF87-A2B61D3A7671}.Debug.Build.0 = Debug|Win32 - {C57C28A3-4FE0-6208-BF87-A2B61D3A7671}.Release.ActiveCfg = Release|Win32 - {C57C28A3-4FE0-6208-BF87-A2B61D3A7671}.Release.Build.0 = Release|Win32 {C57C25A3-4620-FE08-F8B7-AB673D762B60}.Debug.ActiveCfg = Debug|Win32 {C57C25A3-4620-FE08-F8B7-AB673D762B60}.Debug.Build.0 = Debug|Win32 {C57C25A3-4620-FE08-F8B7-AB673D762B60}.Release.ActiveCfg = Release|Win32 {C57C25A3-4620-FE08-F8B7-AB673D762B60}.Release.Build.0 = Release|Win32 + {C57C28A3-4FE0-6208-BF87-B2B61D3A7674}.Debug.ActiveCfg = Debug|Win32 + {C57C28A3-4FE0-6208-BF87-B2B61D3A7674}.Debug.Build.0 = Debug|Win32 + {C57C28A3-4FE0-6208-BF87-B2B61D3A7674}.Release.ActiveCfg = Release|Win32 + {C57C28A3-4FE0-6208-BF87-B2B61D3A7674}.Release.Build.0 = Release|Win32 + {C57C28A3-4FE0-6208-BF87-B2B61D3A7676}.Debug.ActiveCfg = Debug|Win32 + {C57C28A3-4FE0-6208-BF87-B2B61D3A7676}.Debug.Build.0 = Debug|Win32 + {C57C28A3-4FE0-6208-BF87-B2B61D3A7676}.Release.ActiveCfg = Release|Win32 + {C57C28A3-4FE0-6208-BF87-B2B61D3A7676}.Release.Build.0 = Release|Win32 + {C57C28A3-4FE0-6208-BF87-B2B61D3A7673}.Debug.ActiveCfg = Debug|Win32 + {C57C28A3-4FE0-6208-BF87-B2B61D3A7673}.Debug.Build.0 = Debug|Win32 + {C57C28A3-4FE0-6208-BF87-B2B61D3A7673}.Release.ActiveCfg = Release|Win32 + {C57C28A3-4FE0-6208-BF87-B2B61D3A7673}.Release.Build.0 = Release|Win32 + {C57C28A3-4FE0-6208-BF87-B2B61D3A7672}.Debug.ActiveCfg = Debug|Win32 + {C57C28A3-4FE0-6208-BF87-B2B61D3A7672}.Debug.Build.0 = Debug|Win32 + {C57C28A3-4FE0-6208-BF87-B2B61D3A7672}.Release.ActiveCfg = Release|Win32 + {C57C28A3-4FE0-6208-BF87-B2B61D3A7672}.Release.Build.0 = Release|Win32 + {C57C28A3-4FE0-6208-BF87-B2B61D3A7671}.Debug.ActiveCfg = Debug|Win32 + {C57C28A3-4FE0-6208-BF87-B2B61D3A7671}.Debug.Build.0 = Debug|Win32 + {C57C28A3-4FE0-6208-BF87-B2B61D3A7671}.Release.ActiveCfg = Release|Win32 + {C57C28A3-4FE0-6208-BF87-B2B61D3A7671}.Release.Build.0 = Release|Win32 + {C57C28A3-4FE0-6208-BF87-B2B61D3A7670}.Debug.ActiveCfg = Debug|Win32 + {C57C28A3-4FE0-6208-BF87-B2B61D3A7670}.Debug.Build.0 = Debug|Win32 + {C57C28A3-4FE0-6208-BF87-B2B61D3A7670}.Release.ActiveCfg = Release|Win32 + {C57C28A3-4FE0-6208-BF87-B2B61D3A7670}.Release.Build.0 = Release|Win32 + {C57C28A3-4FE0-6208-BF87-B2B61D3A7675}.Debug.ActiveCfg = Debug|Win32 + {C57C28A3-4FE0-6208-BF87-B2B61D3A7675}.Debug.Build.0 = Debug|Win32 + {C57C28A3-4FE0-6208-BF87-B2B61D3A7675}.Release.ActiveCfg = Release|Win32 + {C57C28A3-4FE0-6208-BF87-B2B61D3A7675}.Release.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionItems) = postSolution ..\..\..\..\boost\move\algorithm.hpp = ..\..\..\..\boost\move\algorithm.hpp @@ -182,6 +230,8 @@ Global ..\..\..\..\boost\move\detail\move_helpers.hpp = ..\..\..\..\boost\move\detail\move_helpers.hpp ..\..\..\..\boost\move\traits.hpp = ..\..\..\..\boost\move\traits.hpp ..\..\..\..\boost\move\unique_ptr.hpp = ..\..\..\..\boost\move\unique_ptr.hpp + ..\..\test\unique_ptr_test_utils_beg.hpp = ..\..\test\unique_ptr_test_utils_beg.hpp + ..\..\test\unique_ptr_test_utils_end.hpp = ..\..\test\unique_ptr_test_utils_end.hpp ..\..\..\..\boost\move\utility.hpp = ..\..\..\..\boost\move\utility.hpp ..\..\..\..\boost\move\utility_core.hpp = ..\..\..\..\boost\move\utility_core.hpp ..\..\..\..\boost\move\detail\workaround.hpp = ..\..\..\..\boost\move\detail\workaround.hpp diff --git a/proj/vc7ide/unique_ptr_assign_test.vcproj b/proj/vc7ide/unique_ptr_assign_test.vcproj new file mode 100644 index 0000000..941d51e --- /dev/null +++ b/proj/vc7ide/unique_ptr_assign_test.vcproj @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/unique_ptr_ctordtor_test.vcproj b/proj/vc7ide/unique_ptr_ctordtor_test.vcproj new file mode 100644 index 0000000..50bec36 --- /dev/null +++ b/proj/vc7ide/unique_ptr_ctordtor_test.vcproj @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/unique_ptr_modifiers_test.vcproj b/proj/vc7ide/unique_ptr_modifiers_test.vcproj new file mode 100644 index 0000000..120d483 --- /dev/null +++ b/proj/vc7ide/unique_ptr_modifiers_test.vcproj @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/unique_ptr_movector_test.vcproj b/proj/vc7ide/unique_ptr_movector_test.vcproj new file mode 100644 index 0000000..6c79449 --- /dev/null +++ b/proj/vc7ide/unique_ptr_movector_test.vcproj @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/unique_ptr_nullptr_test.vcproj b/proj/vc7ide/unique_ptr_nullptr_test.vcproj new file mode 100644 index 0000000..1ff8e57 --- /dev/null +++ b/proj/vc7ide/unique_ptr_nullptr_test.vcproj @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/unique_ptr_observers_test.vcproj b/proj/vc7ide/unique_ptr_observers_test.vcproj new file mode 100644 index 0000000..abfbf87 --- /dev/null +++ b/proj/vc7ide/unique_ptr_observers_test.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/unique_ptr_test.vcproj b/proj/vc7ide/unique_ptr_types_test.vcproj similarity index 86% rename from proj/vc7ide/unique_ptr_test.vcproj rename to proj/vc7ide/unique_ptr_types_test.vcproj index 31aca33..9b35a18 100644 --- a/proj/vc7ide/unique_ptr_test.vcproj +++ b/proj/vc7ide/unique_ptr_types_test.vcproj @@ -2,8 +2,8 @@ @@ -68,7 +68,7 @@ + UniqueIdentifier="{7E3495A1-163E-57AC-5A6C-3A2754202BF5}"> + RelativePath="..\..\test\unique_ptr_types.cpp"> diff --git a/test/unique_ptr.cpp b/test/unique_ptr.cpp deleted file mode 100644 index e52a43d..0000000 --- a/test/unique_ptr.cpp +++ /dev/null @@ -1,1983 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Howard Hinnant 2009 -// (C) Copyright Ion Gaztanaga 2014-2014. -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/move for documentation. -// -////////////////////////////////////////////////////////////////////////////// -#include -#include -#include -#include - -////////////////////////////////////////////// -// -// The initial implementation of these tests -// was written by Howard Hinnant. -// -// These test were later refactored grouping -// and porting them to Boost.Move. -// -// Many thanks to Howard for releasing his C++03 -// unique_ptr implementation with such detailed -// test cases. -// -////////////////////////////////////////////// - -namespace bml = ::boost::movelib; - -//A deleter that can only default constructed -template -class def_constr_deleter -{ - int state_; - def_constr_deleter(const def_constr_deleter&); - def_constr_deleter& operator=(const def_constr_deleter&); - - public: - typedef typename ::boost::move_detail::remove_extent::type element_type; - static const bool is_array = ::boost::move_detail::is_array::value; - - def_constr_deleter() : state_(5) {} - - explicit def_constr_deleter(int s) : state_(s) {} - - int state() const {return state_;} - - void set_state(int s) {state_ = s;} - - void operator()(element_type* p) const - { is_array ? delete []p : delete p; } - - void operator()(element_type* p) - { ++state_; is_array ? delete []p : delete p; } -}; - -//A deleter that can be copy constructed -template -class copy_constr_deleter -{ - int state_; - - public: - typedef typename ::boost::move_detail::remove_extent::type element_type; - static const bool is_array = ::boost::move_detail::is_array::value; - - copy_constr_deleter() : state_(5) {} - - template - copy_constr_deleter(const copy_constr_deleter& - , typename boost::move_detail::enable_def_del::type* =0) - { state_ = 5; } - - explicit copy_constr_deleter(int s) : state_(s) {} - - template - typename boost::move_detail::enable_def_del::type - operator=(const copy_constr_deleter &d) - { - state_ = d.state(); - return *this; - } - - int state() const {return state_;} - - void set_state(int s) {state_ = s;} - - void operator()(element_type* p) const - { is_array ? delete []p : delete p; } - - void operator()(element_type* p) - { ++state_; is_array ? delete []p : delete p; } -}; - -//A deleter that can be only move constructed -template -class move_constr_deleter -{ - int state_; - - BOOST_MOVABLE_BUT_NOT_COPYABLE(move_constr_deleter) - - public: - typedef typename ::boost::move_detail::remove_extent::type element_type; - static const bool is_array = ::boost::move_detail::is_array::value; - - move_constr_deleter() : state_(5) {} - - move_constr_deleter(BOOST_RV_REF(move_constr_deleter) r) - : state_(r.state_) - { r.state_ = 0; } - - explicit move_constr_deleter(int s) : state_(s) {} - - template - move_constr_deleter(BOOST_RV_REF(move_constr_deleter) d - , typename boost::move_detail::enable_def_del::type* =0) - : state_(d.state()) - { d.set_state(0); } - - move_constr_deleter& operator=(BOOST_RV_REF(move_constr_deleter) r) - { - state_ = r.state_; - r.state_ = 0; - return *this; - } - - template - typename boost::move_detail::enable_def_del::type - operator=(BOOST_RV_REF(move_constr_deleter) d) - { - state_ = d.state(); - d.set_state(0); - return *this; - } - - int state() const {return state_;} - - void set_state(int s) {state_ = s;} - - void operator()(element_type* p) const - { is_array ? delete []p : delete p; } - - void operator()(element_type* p) - { ++state_; is_array ? delete []p : delete p; } - - friend bool operator==(const move_constr_deleter& x, const move_constr_deleter& y) - {return x.state_ == y.state_;} -}; - -//A base class containing state with a static instance counter -struct A -{ - int state_; - static int count; - - A() : state_(999) {++count;} - explicit A(int i) : state_(i) {++count;} - A(const A& a) : state_(a.state_) {++count;} - A& operator=(const A& a) { state_ = a.state_; return *this; } - void set(int i) {state_ = i;} - virtual ~A() {--count;} - friend bool operator==(const A& x, const A& y) { return x.state_ == y.state_; } -}; - -int A::count = 0; - -//A class derived from A with a static instance counter -struct B - : public A -{ - static int count; - B() {++count;} - B(const B&) {++count;} - virtual ~B() {--count;} -}; - -int B::count = 0; - -void reset_counters(); - -BOOST_STATIC_ASSERT((::boost::move_detail::is_convertible::value)); - -//Incomplete Type -struct I; -void check(int i); -I* get(); -I* get_array(int i); - -template > -struct J -{ - typedef bml::unique_ptr unique_ptr_type; - typedef typename unique_ptr_type::element_type element_type; - bml::unique_ptr a_; - J() {} - explicit J(element_type*a) : a_(a) {} - ~J(); - - element_type* get() const {return a_.get();} - D& get_deleter() {return a_.get_deleter();} -}; - -//////////////////////////////// -// pointer_type -//////////////////////////////// -namespace pointer_type { - -struct Deleter -{ - struct pointer {}; -}; - -// Test unique_ptr::pointer type -void test() -{ - //Single unique_ptr - { - typedef bml::unique_ptr P; - BOOST_STATIC_ASSERT((boost::move_detail::is_same::value)); - } - { - typedef bml::unique_ptr P; - BOOST_STATIC_ASSERT((boost::move_detail::is_same::value)); - } - //Array unique_ptr - { - typedef bml::unique_ptr P; - BOOST_STATIC_ASSERT((boost::move_detail::is_same::value)); - } - { - typedef bml::unique_ptr P; - BOOST_STATIC_ASSERT((boost::move_detail::is_same::value)); - } -} - -} //namespace pointer_type { - -//////////////////////////////// -// unique_ptr_asgn_move_convert01 -//////////////////////////////// -namespace unique_ptr_asgn_move_convert01 { - -void test() -{ - //Single unique_ptr - reset_counters(); - { - bml::unique_ptr s(new B); - A* p = s.get(); - bml::unique_ptr s2(new A); - BOOST_TEST(A::count == 2); - s2 = boost::move(s); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s.get() == 0); - BOOST_TEST(A::count == 1); - BOOST_TEST(B::count == 1); - } - BOOST_TEST(A::count == 0); - BOOST_TEST(B::count == 0); - - reset_counters(); - //Array unique_ptr, only from the same CV qualified pointers - { - bml::unique_ptr s(new A[2]); - A* p = s.get(); - bml::unique_ptr s2(new const A[2]); - BOOST_TEST(A::count == 4); - s2 = boost::move(s); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s.get() == 0); - BOOST_TEST(A::count == 2); - } - BOOST_TEST(A::count == 0); -} - -} //namespace unique_ptr_asgn_move_convert01{ - -//////////////////////////////// -// unique_ptr_asgn_move_convert02 -//////////////////////////////// - -namespace unique_ptr_asgn_move_convert02{ - -void test() -{ - //Single unique_ptr - reset_counters(); - { - bml::unique_ptr > s(new B); - A* p = s.get(); - bml::unique_ptr > s2(new A); - BOOST_TEST(A::count == 2); - s2 = (boost::move(s)); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s.get() == 0); - BOOST_TEST(A::count == 1); - BOOST_TEST(B::count == 1); - BOOST_TEST(s2.get_deleter().state() == 5); - BOOST_TEST(s.get_deleter().state() == 0); - } - BOOST_TEST(A::count == 0); - BOOST_TEST(B::count == 0); - - //Array unique_ptr, only from the same CV qualified pointers - reset_counters(); - { - bml::unique_ptr > s(new A[2]); - A* p = s.get(); - bml::unique_ptr > s2(new const A[2]); - BOOST_TEST(A::count == 4); - s2 = (boost::move(s)); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s.get() == 0); - BOOST_TEST(A::count == 2); - BOOST_TEST(s2.get_deleter().state() == 5); - BOOST_TEST(s.get_deleter().state() == 0); - } - BOOST_TEST(A::count == 0); -} - -} //namespace unique_ptr_asgn_move_convert02{ - -//////////////////////////////// -// unique_ptr_asgn_move_convert03 -//////////////////////////////// - -namespace unique_ptr_asgn_move_convert03{ - -// test converting move assignment with reference deleters - -void test() -{ - //Single unique_ptr - reset_counters(); - { - copy_constr_deleter db(5); - bml::unique_ptr&> s(new B, db); - A* p = s.get(); - copy_constr_deleter da(6); - bml::unique_ptr&> s2(new A, da); - s2 = boost::move(s); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s.get() == 0); - BOOST_TEST(A::count == 1); - BOOST_TEST(B::count == 1); - BOOST_TEST(s2.get_deleter().state() == 5); - } - BOOST_TEST(A::count == 0); - BOOST_TEST(B::count == 0); - - //Array unique_ptr, only from the same CV qualified pointers - reset_counters(); - { - copy_constr_deleter db(5); - bml::unique_ptr&> s(new A[2], db); - A* p = s.get(); - copy_constr_deleter da(6); - bml::unique_ptr&> s2(new const A[2], da); - BOOST_TEST(A::count == 4); - s2 = boost::move(s); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s.get() == 0); - BOOST_TEST(A::count == 2); - BOOST_TEST(s2.get_deleter().state() == 5); - } - BOOST_TEST(A::count == 0); - BOOST_TEST(B::count == 0); -} - -} //namespace unique_ptr_asgn_move_convert03{ - -//////////////////////////////// -// unique_ptr_asgn_move01 -//////////////////////////////// -namespace unique_ptr_asgn_move01 { - -void test() -{ - //Single unique_ptr - reset_counters(); - { - bml::unique_ptr s1(new A); - A* p = s1.get(); - bml::unique_ptr s2(new A); - BOOST_TEST(A::count == 2); - s2 = boost::move(s1); - BOOST_TEST(A::count == 1); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s1.get() == 0); - } - BOOST_TEST(A::count == 0); - { - bml::unique_ptr > s1(new A); - A* p = s1.get(); - bml::unique_ptr > s2(new A); - BOOST_TEST(A::count == 2); - s2 = boost::move(s1); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s1.get() == 0); - BOOST_TEST(A::count == 1); - BOOST_TEST(s2.get_deleter().state() == 5); - BOOST_TEST(s1.get_deleter().state() == 0); - } - BOOST_TEST(A::count == 0); - { - copy_constr_deleter d1(5); - bml::unique_ptr&> s1(new A, d1); - A* p = s1.get(); - copy_constr_deleter d2(6); - bml::unique_ptr&> s2(new A, d2); - s2 = boost::move(s1); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s1.get() == 0); - BOOST_TEST(A::count == 1); - BOOST_TEST(d1.state() == 5); - BOOST_TEST(d2.state() == 5); - } - BOOST_TEST(A::count == 0); - - //Array unique_ptr - reset_counters(); - { - bml::unique_ptr s1(new A[2]); - A* p = s1.get(); - bml::unique_ptr s2(new A[2]); - BOOST_TEST(A::count == 4); - s2 = boost::move(s1); - BOOST_TEST(A::count == 2); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s1.get() == 0); - } - BOOST_TEST(A::count == 0); - { - bml::unique_ptr > s1(new A[2]); - A* p = s1.get(); - bml::unique_ptr > s2(new A[2]); - BOOST_TEST(A::count == 4); - s2 = boost::move(s1); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s1.get() == 0); - BOOST_TEST(A::count == 2); - BOOST_TEST(s2.get_deleter().state() == 5); - BOOST_TEST(s1.get_deleter().state() == 0); - } - BOOST_TEST(A::count == 0); - { - copy_constr_deleter d1(5); - bml::unique_ptr&> s1(new A[2], d1); - A* p = s1.get(); - copy_constr_deleter d2(6); - bml::unique_ptr&> s2(new A[2], d2); - BOOST_TEST(A::count == 4); - s2 = boost::move(s1); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s1.get() == 0); - BOOST_TEST(A::count == 2); - BOOST_TEST(d1.state() == 5); - BOOST_TEST(d2.state() == 5); - } - BOOST_TEST(A::count == 0); -} - -} //unique_ptr_asgn_move01 - -//////////////////////////////// -// unique_ptr_ctor_default01 -//////////////////////////////// - -namespace unique_ptr_ctor_default01{ - -// default unique_ptr ctor should only require default deleter ctor - -void test() -{ - //Single unique_ptr - { - bml::unique_ptr p; - BOOST_TEST(p.get() == 0); - } - { - bml::unique_ptr > p; - BOOST_TEST(p.get() == 0); - BOOST_TEST(p.get_deleter().state() == 5); - } - //Array unique_ptr - { - bml::unique_ptr p; - BOOST_TEST(p.get() == 0); - } - { - bml::unique_ptr > p; - BOOST_TEST(p.get() == 0); - BOOST_TEST(p.get_deleter().state() == 5); - } -} - -} //namespace unique_ptr_ctor_default01{ - -//////////////////////////////// -// unique_ptr_ctor_default02 -//////////////////////////////// - -namespace unique_ptr_ctor_default02{ - -// default unique_ptr ctor shouldn't require complete type - -void test() -{ - //Single unique_ptr - reset_counters(); - { - J s; - BOOST_TEST(s.get() == 0); - } - check(0); - { - J > s; - BOOST_TEST(s.get() == 0); - BOOST_TEST(s.get_deleter().state() == 5); - } - check(0); - //Array unique_ptr - reset_counters(); - { - J s; - BOOST_TEST(s.get() == 0); - } - check(0); - { - J > s; - BOOST_TEST(s.get() == 0); - BOOST_TEST(s.get_deleter().state() == 5); - } - check(0); -} - -} //namespace unique_ptr_ctor_default02{ - -//////////////////////////////// -// unique_ptr_ctor_move_convert01 -//////////////////////////////// - -namespace unique_ptr_ctor_move_convert01{ - -// test converting move ctor. Should only require a MoveConstructible deleter, or if -// deleter is a reference, not even that. -// Explicit version - -void test() -{ - //Single unique_ptr - reset_counters(); - { - bml::unique_ptr s(new B); - A* p = s.get(); - bml::unique_ptr s2(boost::move(s)); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s.get() == 0); - BOOST_TEST(A::count == 1); - BOOST_TEST(B::count == 1); - } - BOOST_TEST(A::count == 0); - BOOST_TEST(B::count == 0); - //Array unique_ptr, only from the same CV qualified pointers - reset_counters(); - { - bml::unique_ptr s(new A[2]); - A* p = s.get(); - bml::unique_ptr s2(boost::move(s)); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s.get() == 0); - BOOST_TEST(A::count == 2); - } - BOOST_TEST(A::count == 0); -} - -} //namespace unique_ptr_ctor_move_convert01{ - -//////////////////////////////// -// unique_ptr_ctor_move_convert02 -//////////////////////////////// - -namespace unique_ptr_ctor_move_convert02{ - -// test converting move ctor. Should only require a MoveConstructible deleter, or if -// deleter is a reference, not even that. -// Explicit version - -void test() -{ - //Single unique_ptr - reset_counters(); - BOOST_STATIC_ASSERT((boost::move_detail::is_convertible::value)); - { - bml::unique_ptr > s(new B); - A* p = s.get(); - bml::unique_ptr > s2(boost::move(s)); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s.get() == 0); - BOOST_TEST(A::count == 1); - BOOST_TEST(B::count == 1); - BOOST_TEST(s2.get_deleter().state() == 5); - BOOST_TEST(s.get_deleter().state() == 0); - } - BOOST_TEST(A::count == 0); - BOOST_TEST(B::count == 0); - //Array unique_ptr, only from the same CV qualified pointers - reset_counters(); - { - bml::unique_ptr > s(new const A[2]); - const A* p = s.get(); - bml::unique_ptr > s2(boost::move(s)); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s.get() == 0); - BOOST_TEST(A::count == 2); - BOOST_TEST(s2.get_deleter().state() == 5); - BOOST_TEST(s.get_deleter().state() == 0); - } - BOOST_TEST(A::count == 0); - BOOST_TEST(B::count == 0); -} - -} //namespace unique_ptr_ctor_move_convert02{ - -//////////////////////////////// -// unique_ptr_ctor_move_convert03 -//////////////////////////////// - -namespace unique_ptr_ctor_move_convert03{ - -// test converting move ctor. Should only require a MoveConstructible deleter, or if -// deleter is a reference, not even that. -// Explicit version - -void test() -{ - //Single unique_ptr - reset_counters(); - { - def_constr_deleter d; - bml::unique_ptr&> s(new B, d); - A* p = s.get(); - bml::unique_ptr&> s2(boost::move(s)); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s.get() == 0); - BOOST_TEST(A::count == 1); - BOOST_TEST(B::count == 1); - d.set_state(6); - BOOST_TEST(s2.get_deleter().state() == d.state()); - BOOST_TEST(s.get_deleter().state() == d.state()); - } - BOOST_TEST(A::count == 0); - BOOST_TEST(B::count == 0); - //Array unique_ptr, only from the same CV qualified pointers - reset_counters(); - { - def_constr_deleter d; - bml::unique_ptr&> s(new A[2], d); - A* p = s.get(); - bml::unique_ptr&> s2(boost::move(s)); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s.get() == 0); - BOOST_TEST(A::count == 2); - d.set_state(6); - BOOST_TEST(s2.get_deleter().state() == d.state()); - BOOST_TEST(s.get_deleter().state() == d.state()); - } - BOOST_TEST(A::count == 0); -} - -} //namespace unique_ptr_ctor_move_convert03{ - -//////////////////////////////// -// unique_ptr_ctor_move_convert04 -//////////////////////////////// - -namespace unique_ptr_ctor_move_convert04{ - -// test converting move ctor. Should only require a MoveConstructible deleter, or if -// deleter is a reference, not even that. -// implicit version - -void test() -{ - //Single unique_ptr - reset_counters(); - { - bml::unique_ptr s(new B); - A* p = s.get(); - bml::unique_ptr s2(boost::move(s)); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s.get() == 0); - BOOST_TEST(A::count == 1); - BOOST_TEST(B::count == 1); - } - BOOST_TEST(A::count == 0); - BOOST_TEST(B::count == 0); - //Array unique_ptr, only from the same CV qualified pointers - reset_counters(); - { - bml::unique_ptr s(new A[2]); - A* p = s.get(); - bml::unique_ptr s2(boost::move(s)); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s.get() == 0); - BOOST_TEST(A::count == 2); - } - BOOST_TEST(A::count == 0); -} - -} //namespace unique_ptr_ctor_move_convert04{ - -//////////////////////////////// -// unique_ptr_ctor_move_convert05 -//////////////////////////////// - -namespace unique_ptr_ctor_move_convert05{ - -// test converting move ctor. Should only require a MoveConstructible deleter, or if -// deleter is a reference, not even that. -// Implicit version - -void test() -{ - //Single unique_ptr - reset_counters(); - { - bml::unique_ptr > s(new B); - A* p = s.get(); - bml::unique_ptr > s2(boost::move(s)); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s.get() == 0); - BOOST_TEST(A::count == 1); - BOOST_TEST(B::count == 1); - BOOST_TEST(s2.get_deleter().state() == 5); - BOOST_TEST(s.get_deleter().state() == 0); - } - BOOST_TEST(A::count == 0); - BOOST_TEST(B::count == 0); - //Array unique_ptr, only from the same CV qualified pointers - reset_counters(); - { - bml::unique_ptr > s(new const A[2]); - const A* p = s.get(); - bml::unique_ptr > s2(boost::move(s)); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s.get() == 0); - BOOST_TEST(A::count == 2); - BOOST_TEST(s2.get_deleter().state() == 5); - BOOST_TEST(s.get_deleter().state() == 0); - } - BOOST_TEST(A::count == 0); -} - -} //namespace unique_ptr_ctor_move_convert05{ - -//////////////////////////////// -// unique_ptr_ctor_move_convert06 -//////////////////////////////// - -namespace unique_ptr_ctor_move_convert06{ - -// test converting move ctor. Should only require a MoveConstructible deleter, or if -// deleter is a reference, not even that. -// Implicit version - -void test() -{ - //Single unique_ptr - reset_counters(); - { - def_constr_deleter d; - bml::unique_ptr&> s(new B, d); - A* p = s.get(); - bml::unique_ptr&> s2(boost::move(s)); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s.get() == 0); - BOOST_TEST(A::count == 1); - BOOST_TEST(B::count == 1); - d.set_state(6); - BOOST_TEST(s2.get_deleter().state() == d.state()); - BOOST_TEST(s.get_deleter().state() == d.state()); - } - BOOST_TEST(A::count == 0); - BOOST_TEST(B::count == 0); - //Array unique_ptr, only from the same CV qualified pointers - reset_counters(); - { - def_constr_deleter d; - bml::unique_ptr&> s(new volatile A[2], d); - volatile A* p = s.get(); - bml::unique_ptr&> s2(boost::move(s)); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s.get() == 0); - BOOST_TEST(A::count == 2); - d.set_state(6); - BOOST_TEST(s2.get_deleter().state() == d.state()); - BOOST_TEST(s.get_deleter().state() == d.state()); - } - BOOST_TEST(A::count == 0); -} - -} //namespace unique_ptr_ctor_move_convert06{ - -//////////////////////////////// -// unique_ptr_ctor_move01 -//////////////////////////////// - -namespace unique_ptr_ctor_move01{ - -// test converting move ctor. Should only require a MoveConstructible deleter, or if -// deleter is a reference, not even that. -// Implicit version - -void test() -{ - //Single unique_ptr - reset_counters(); - { - bml::unique_ptr s(new A); - A* p = s.get(); - bml::unique_ptr s2 = boost::move(s); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s.get() == 0); - BOOST_TEST(A::count == 1); - } - BOOST_TEST(A::count == 0); - { - bml::unique_ptr > s(new A); - A* p = s.get(); - bml::unique_ptr > s2 = boost::move(s); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s.get() == 0); - BOOST_TEST(A::count == 1); - BOOST_TEST(s2.get_deleter().state() == 5); - BOOST_TEST(s.get_deleter().state() == 0); - } - BOOST_TEST(A::count == 0); - { - def_constr_deleter d; - bml::unique_ptr&> s(new A, d); - A* p = s.get(); - bml::unique_ptr&> s2 = boost::move(s); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s.get() == 0); - BOOST_TEST(A::count == 1); - d.set_state(6); - BOOST_TEST(s2.get_deleter().state() == d.state()); - BOOST_TEST(s.get_deleter().state() == d.state()); - } - BOOST_TEST(A::count == 0); - //Array unique_ptr - reset_counters(); - { - bml::unique_ptr s(new A[2]); - A* p = s.get(); - bml::unique_ptr s2 = boost::move(s); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s.get() == 0); - BOOST_TEST(A::count == 2); - } - BOOST_TEST(A::count == 0); - { - bml::unique_ptr > s(new A[2]); - A* p = s.get(); - bml::unique_ptr > s2 = boost::move(s); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s.get() == 0); - BOOST_TEST(A::count == 2); - BOOST_TEST(s2.get_deleter().state() == 5); - BOOST_TEST(s.get_deleter().state() == 0); - } - BOOST_TEST(A::count == 0); - { - def_constr_deleter d; - bml::unique_ptr&> s(new A[2], d); - A* p = s.get(); - bml::unique_ptr&> s2 = boost::move(s); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s.get() == 0); - BOOST_TEST(A::count == 2); - d.set_state(6); - BOOST_TEST(s2.get_deleter().state() == d.state()); - BOOST_TEST(s.get_deleter().state() == d.state()); - } - BOOST_TEST(A::count == 0); -} - -} //namespace unique_ptr_ctor_move01{ - -//////////////////////////////// -// unique_ptr_ctor_move02 -//////////////////////////////// - -namespace unique_ptr_ctor_move02{ - -// test move ctor. Should only require a MoveConstructible deleter, or if -// deleter is a reference, not even that. - -bml::unique_ptr source1() -{ return bml::unique_ptr(new A); } - -bml::unique_ptr source1_array() -{ return bml::unique_ptr (new A[2]); } - -void sink1(bml::unique_ptr) -{} - -void sink1_array(bml::unique_ptr) -{} - -bml::unique_ptr > source2() -{ return bml::unique_ptr > (new A); } - -bml::unique_ptr > source2_array() -{ return bml::unique_ptr >(new A[2]); } - -void sink2(bml::unique_ptr >) -{} - -void sink2_array(bml::unique_ptr >) -{} - -bml::unique_ptr&> source3() -{ - static def_constr_deleter d; - return bml::unique_ptr&>(new A, d); -} - -bml::unique_ptr&> source3_array() -{ - static def_constr_deleter d; - return bml::unique_ptr&>(new A[2], d); -} - -void sink3(bml::unique_ptr&> ) -{} - -void sink3_array(bml::unique_ptr&> ) -{} - -void test() -{ - //Single unique_ptr - reset_counters(); - sink1(source1()); - sink2(source2()); - sink3(source3()); - BOOST_TEST(A::count == 0); - //Array unique_ptr - reset_counters(); - sink1_array(source1_array()); - sink2_array(source2_array()); - sink3_array(source3_array()); - BOOST_TEST(A::count == 0); -} - -} //namespace unique_ptr_ctor_move02{ - -//////////////////////////////// -// unique_ptr_ctor_pointer_deleter01 -//////////////////////////////// - -namespace unique_ptr_ctor_pointer_deleter01{ - -// test move ctor. Should only require a MoveConstructible deleter, or if -// deleter is a reference, not even that. - -// unique_ptr(pointer, deleter()) only requires MoveConstructible deleter - -void test() -{ - //Single unique_ptr - reset_counters(); - { - A* p = new A; - BOOST_TEST(A::count == 1); - move_constr_deleter d; - bml::unique_ptr > s(p, ::boost::move(d)); - BOOST_TEST(s.get() == p); - BOOST_TEST(s.get_deleter().state() == 5); - bml::unique_ptr > s2(s.release(), move_constr_deleter(6)); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s2.get_deleter().state() == 6); - } - BOOST_TEST(A::count == 0); - //Array unique_ptr - reset_counters(); - { - A* p = new A[2]; - BOOST_TEST(A::count == 2); - move_constr_deleter d; - bml::unique_ptr > s(p, ::boost::move(d)); - BOOST_TEST(s.get() == p); - BOOST_TEST(s.get_deleter().state() == 5); - bml::unique_ptr > s2(s.release(), move_constr_deleter(6)); - BOOST_TEST(s2.get() == p); - BOOST_TEST(s2.get_deleter().state() == 6); - } - BOOST_TEST(A::count == 0); -} - -} //namespace unique_ptr_ctor_pointer_deleter01{ - -//////////////////////////////// -// unique_ptr_ctor_pointer_deleter02 -//////////////////////////////// - -namespace unique_ptr_ctor_pointer_deleter02{ - -// unique_ptr(pointer, d) requires CopyConstructible deleter - -void test() -{ - //Single unique_ptr - reset_counters(); - { - A* p = new A; - BOOST_TEST(A::count == 1); - copy_constr_deleter d; - bml::unique_ptr > s(p, d); - BOOST_TEST(s.get() == p); - BOOST_TEST(s.get_deleter().state() == 5); - d.set_state(6); - BOOST_TEST(s.get_deleter().state() == 5); - } - BOOST_TEST(A::count == 0); - //Array unique_ptr - reset_counters(); - { - A* p = new A[2]; - BOOST_TEST(A::count == 2); - copy_constr_deleter d; - bml::unique_ptr > s(p, d); - BOOST_TEST(s.get() == p); - BOOST_TEST(s.get_deleter().state() == 5); - d.set_state(6); - BOOST_TEST(s.get_deleter().state() == 5); - } - BOOST_TEST(A::count == 0); -} - -} //namespace unique_ptr_ctor_pointer_deleter02{ - -//////////////////////////////// -// unique_ptr_ctor_pointer_deleter03 -//////////////////////////////// - -namespace unique_ptr_ctor_pointer_deleter03{ - -// unique_ptr(pointer, d) does not requires CopyConstructible deleter - -void test() -{ - //Single unique_ptr - reset_counters(); - { - A* p = new A; - BOOST_TEST(A::count == 1); - def_constr_deleter d; - bml::unique_ptr&> s(p, d); - BOOST_TEST(s.get() == p); - BOOST_TEST(s.get_deleter().state() == 5); - d.set_state(6); - BOOST_TEST(s.get_deleter().state() == 6); - } - BOOST_TEST(A::count == 0); - //Array unique_ptr - reset_counters(); - { - A* p = new A[2]; - BOOST_TEST(A::count == 2); - def_constr_deleter d; - bml::unique_ptr&> s(p, d); - BOOST_TEST(s.get() == p); - BOOST_TEST(s.get_deleter().state() == 5); - d.set_state(6); - BOOST_TEST(s.get_deleter().state() == 6); - } - BOOST_TEST(A::count == 0); -} - -} //namespace unique_ptr_ctor_pointer_deleter03{ - -//////////////////////////////// -// unique_ptr_ctor_pointer_deleter04 -//////////////////////////////// - -namespace unique_ptr_ctor_pointer_deleter04{ - -// unique_ptr(pointer, d) does not requires CopyConstructible deleter - -void test() -{ - //Single unique_ptr - reset_counters(); - { - A* p = new A; - BOOST_TEST(A::count == 1); - def_constr_deleter d; - bml::unique_ptr&> s(p, d); - BOOST_TEST(s.get() == p); - BOOST_TEST(s.get_deleter().state() == 5); - } - BOOST_TEST(A::count == 0); - //Array unique_ptr - reset_counters(); - { - A* p = new A[2]; - BOOST_TEST(A::count == 2); - def_constr_deleter d; - bml::unique_ptr&> s(p, d); - BOOST_TEST(s.get() == p); - BOOST_TEST(s.get_deleter().state() == 5); - } - BOOST_TEST(A::count == 0); -} - -} //namespace unique_ptr_ctor_pointer_deleter04{ - -//////////////////////////////// -// unique_ptr_ctor_pointer_deleter05 -//////////////////////////////// - -namespace unique_ptr_ctor_pointer_deleter05{ - -// unique_ptr(pointer, deleter) should work with derived pointers -// or same (cv aside) types for array unique_ptrs - -void test() -{ - //Single unique_ptr - reset_counters(); - { - B* p = new B; - BOOST_TEST(A::count == 1); - BOOST_TEST(B::count == 1); - bml::unique_ptr > s(p, copy_constr_deleter()); - BOOST_TEST(s.get() == p); - BOOST_TEST(s.get_deleter().state() == 5); - } - BOOST_TEST(A::count == 0); - BOOST_TEST(B::count == 0); - //Array unique_ptr - reset_counters(); - { - A* p = new A[2]; - BOOST_TEST(A::count == 2); - bml::unique_ptr > s(p, copy_constr_deleter()); - BOOST_TEST(s.get() == p); - BOOST_TEST(s.get_deleter().state() == 5); - } - BOOST_TEST(A::count == 0); - BOOST_TEST(B::count == 0); -} - -} //namespace unique_ptr_ctor_pointer_deleter05{ - -//////////////////////////////// -// unique_ptr_ctor_pointer_deleter06 -//////////////////////////////// - -namespace unique_ptr_ctor_pointer_deleter06{ - -// unique_ptr(pointer, deleter) should work with function pointers -// unique_ptr should work - -bool my_free_called = false; - -void my_free(void*) -{ - my_free_called = true; -} - -void test() -{ - { - int i = 0; - bml::unique_ptr s(&i, my_free); - BOOST_TEST(s.get() == &i); - BOOST_TEST(s.get_deleter() == my_free); - BOOST_TEST(!my_free_called); - } - BOOST_TEST(my_free_called); -} - -} //namespace unique_ptr_ctor_pointer_deleter06{ - -//////////////////////////////// -// unique_ptr_ctor_pointer01 -//////////////////////////////// - -namespace unique_ptr_ctor_pointer01{ - -// unique_ptr(pointer) ctor should only require default deleter ctor - -void test() -{ - //Single unique_ptr - reset_counters(); - { - A* p = new A; - BOOST_TEST(A::count == 1); - bml::unique_ptr s(p); - BOOST_TEST(s.get() == p); - } - BOOST_TEST(A::count == 0); - { - A* p = new A; - BOOST_TEST(A::count == 1); - bml::unique_ptr > s(p); - BOOST_TEST(s.get() == p); - BOOST_TEST(s.get_deleter().state() == 5); - } - BOOST_TEST(A::count == 0); - //Array unique_ptr - reset_counters(); - { - A* p = new A[2]; - BOOST_TEST(A::count == 2); - bml::unique_ptr s(p); - BOOST_TEST(s.get() == p); - } - BOOST_TEST(A::count == 0); - { - A* p = new A[2]; - BOOST_TEST(A::count == 2); - bml::unique_ptr > s(p); - BOOST_TEST(s.get() == p); - BOOST_TEST(s.get_deleter().state() == 5); - } - BOOST_TEST(A::count == 0); -} - -} //namespace unique_ptr_ctor_pointer01{ - -//////////////////////////////// -// unique_ptr_ctor_pointer02 -//////////////////////////////// - -namespace unique_ptr_ctor_pointer02{ - -// unique_ptr(pointer) ctor shouldn't require complete type - -void test() -{ - //Single unique_ptr - reset_counters(); - { - I* p = get(); - check(1); - J s(p); - BOOST_TEST(s.get() == p); - } - check(0); - { - I* p = get(); - check(1); - J > s(p); - BOOST_TEST(s.get() == p); - BOOST_TEST(s.get_deleter().state() == 5); - } - check(0); - //Array unique_ptr - reset_counters(); - { - I* p = get_array(2); - check(2); - J s(p); - BOOST_TEST(s.get() == p); - } - check(0); - { - I* p = get_array(2); - check(2); - J > s(p); - BOOST_TEST(s.get() == p); - BOOST_TEST(s.get_deleter().state() == 5); - } - check(0); -} - -} //namespace unique_ptr_ctor_pointer02{ - -//////////////////////////////// -// unique_ptr_ctor_pointer03 -//////////////////////////////// - -namespace unique_ptr_ctor_pointer03{ - -// unique_ptr(pointer) ctor should work with derived pointers -// or same types (cv aside) for unique_ptr - -void test() -{ - //Single unique_ptr - reset_counters(); - { - B* p = new B; - BOOST_TEST(A::count == 1); - BOOST_TEST(B::count == 1); - bml::unique_ptr s(p); - BOOST_TEST(s.get() == p); - } - BOOST_TEST(A::count == 0); - BOOST_TEST(B::count == 0); - { - B* p = new B; - BOOST_TEST(A::count == 1); - BOOST_TEST(B::count == 1); - bml::unique_ptr > s(p); - BOOST_TEST(s.get() == p); - BOOST_TEST(s.get_deleter().state() == 5); - } - BOOST_TEST(A::count == 0); - BOOST_TEST(B::count == 0); - //Array unique_ptr - reset_counters(); - { - A* p = new A[2]; - BOOST_TEST(A::count == 2); - bml::unique_ptr s(p); - BOOST_TEST(s.get() == p); - } - BOOST_TEST(A::count == 0); - { - const A* p = new const A[2]; - BOOST_TEST(A::count == 2); - bml::unique_ptr > s(p); - BOOST_TEST(s.get() == p); - BOOST_TEST(s.get_deleter().state() == 5); - } - BOOST_TEST(A::count == 0); -} - -} //namespace unique_ptr_ctor_pointer03{ - -//////////////////////////////// -// unique_ptr_dtor_null -//////////////////////////////// - -namespace unique_ptr_dtor_null{ - -// The deleter is not called if get() == 0 - -void test() -{ - //Single unique_ptr - def_constr_deleter d; - BOOST_TEST(d.state() == 5); - { - bml::unique_ptr&> p(0, d); - BOOST_TEST(p.get() == 0); - BOOST_TEST(&p.get_deleter() == &d); - } - BOOST_TEST(d.state() == 5); -} - -} //namespace unique_ptr_dtor_null{ - -//////////////////////////////// -// unique_ptr_modifiers_release -//////////////////////////////// - -namespace unique_ptr_modifiers_release{ - -void test() -{ - //Single unique_ptr - { - bml::unique_ptr p(new int(3)); - int* i = p.get(); - int* j = p.release(); - BOOST_TEST(p.get() == 0); - BOOST_TEST(i == j); - } - //Array unique_ptr - { - bml::unique_ptr p(new int[2]); - int* i = p.get(); - int* j = p.release(); - BOOST_TEST(p.get() == 0); - BOOST_TEST(i == j); - } -} - -} //namespace unique_ptr_modifiers_release{ - -//////////////////////////////// -// unique_ptr_modifiers_reset1 -//////////////////////////////// - -namespace unique_ptr_modifiers_reset1{ - -void test() -{ - //Single unique_ptr - reset_counters(); - { //reset() - bml::unique_ptr p(new A); - BOOST_TEST(A::count == 1); - A* i = p.get(); - (void)i; - p.reset(); - BOOST_TEST(A::count == 0); - BOOST_TEST(p.get() == 0); - } - BOOST_TEST(A::count == 0); - { //reset(p) - bml::unique_ptr p(new A); - BOOST_TEST(A::count == 1); - A* i = p.get(); - (void)i; - p.reset(new A); - BOOST_TEST(A::count == 1); - } - BOOST_TEST(A::count == 0); - { //reset(0) - bml::unique_ptr p(new A); - BOOST_TEST(A::count == 1); - A* i = p.get(); - (void)i; - p.reset(0); - BOOST_TEST(A::count == 0); - BOOST_TEST(p.get() == 0); - } - BOOST_TEST(A::count == 0); - //Array unique_ptr - reset_counters(); - { //reset() - bml::unique_ptr p(new A[2]); - BOOST_TEST(A::count == 2); - A* i = p.get(); - (void)i; - p.reset(); - BOOST_TEST(A::count == 0); - BOOST_TEST(p.get() == 0); - } - BOOST_TEST(A::count == 0); - { //reset(p) - bml::unique_ptr p(new A[2]); - BOOST_TEST(A::count == 2); - A* i = p.get(); - (void)i; - p.reset(new A[3]); - BOOST_TEST(A::count == 3); - } - BOOST_TEST(A::count == 0); - { //reset(0) - bml::unique_ptr p(new A[2]); - BOOST_TEST(A::count == 2); - A* i = p.get(); - (void)i; - p.reset(0); - BOOST_TEST(A::count == 0); - BOOST_TEST(p.get() == 0); - } - BOOST_TEST(A::count == 0); -} - -} //namespace unique_ptr_modifiers_reset1{ - -//////////////////////////////// -// unique_ptr_modifiers_reset2 -//////////////////////////////// - -namespace unique_ptr_modifiers_reset2{ - -void test() -{ - //Single unique_ptr - reset_counters(); - { - bml::unique_ptr p(new A); - BOOST_TEST(A::count == 1); - BOOST_TEST(B::count == 0); - A* i = p.get(); - (void)i; - p.reset(new B); - BOOST_TEST(A::count == 1); - BOOST_TEST(B::count == 1); - } - BOOST_TEST(A::count == 0); - BOOST_TEST(B::count == 0); - { - bml::unique_ptr p(new B); - BOOST_TEST(A::count == 1); - BOOST_TEST(B::count == 1); - A* i = p.get(); - (void)i; - p.reset(new B); - BOOST_TEST(A::count == 1); - BOOST_TEST(B::count == 1); - } - BOOST_TEST(A::count == 0); - BOOST_TEST(B::count == 0); - //Array unique_ptr - reset_counters(); - { - bml::unique_ptr p(new const A[2]); - BOOST_TEST(A::count == 2); - const volatile A* i = p.get(); - (void)i; - p.reset(new volatile A[3]); - BOOST_TEST(A::count == 3); - } - BOOST_TEST(A::count == 0); - { - bml::unique_ptr p(new A[2]); - BOOST_TEST(A::count == 2); - const A* i = p.get(); - (void)i; - p.reset(new const A[3]); - BOOST_TEST(A::count == 3); - } - BOOST_TEST(A::count == 0); -} - -} //unique_ptr_modifiers_reset2 - - -//////////////////////////////// -// unique_ptr_modifiers -//////////////////////////////// - -namespace unique_ptr_modifiers_swap{ - -// test swap - -void test() -{ - //Single unique_ptr - reset_counters(); - { - A* p1 = new A(1); - move_constr_deleter d1(1); - bml::unique_ptr > s1(p1, ::boost::move(d1)); - A* p2 = new A(2); - move_constr_deleter d2(2); - bml::unique_ptr > s2(p2, ::boost::move(d2)); - BOOST_TEST(s1.get() == p1); - BOOST_TEST(*s1 == A(1)); - BOOST_TEST(s1.get_deleter().state() == 1); - BOOST_TEST(s2.get() == p2); - BOOST_TEST(*s2 == A(2)); - BOOST_TEST(s2.get_deleter().state() == 2); - swap(s1, s2); - BOOST_TEST(s1.get() == p2); - BOOST_TEST(*s1 == A(2)); - BOOST_TEST(s1.get_deleter().state() == 2); - BOOST_TEST(s2.get() == p1); - BOOST_TEST(*s2 == A(1)); - BOOST_TEST(s2.get_deleter().state() == 1); - } - //Array unique_ptr - reset_counters(); - { - A* p1 = new A[2]; - p1[0].set(1); - p1[1].set(2); - move_constr_deleter d1(1); - bml::unique_ptr > s1(p1, ::boost::move(d1)); - A* p2 = new A[2]; - p2[0].set(3); - p2[1].set(4); - move_constr_deleter d2(2); - bml::unique_ptr > s2(p2, ::boost::move(d2)); - BOOST_TEST(s1.get() == p1); - BOOST_TEST(s1[0] == A(1)); - BOOST_TEST(s1[1] == A(2)); - BOOST_TEST(s1.get_deleter().state() == 1); - BOOST_TEST(s2.get() == p2); - BOOST_TEST(s2[0] == A(3)); - BOOST_TEST(s2[1] == A(4)); - BOOST_TEST(s2.get_deleter().state() == 2); - swap(s1, s2); - BOOST_TEST(s1.get() == p2); - BOOST_TEST(s1[0] == A(3)); - BOOST_TEST(s1[1] == A(4)); - BOOST_TEST(s1.get_deleter().state() == 2); - BOOST_TEST(s2.get() == p1); - BOOST_TEST(s2[0] == A(1)); - BOOST_TEST(s2[1] == A(2)); - BOOST_TEST(s2.get_deleter().state() == 1); - } -} - -} //namespace unique_ptr_modifiers_swap{ - -//////////////////////////////// -// unique_ptr_observers_dereference -//////////////////////////////// - -namespace unique_ptr_observers_dereference{ - -void test() -{ - //Single unique_ptr - { - bml::unique_ptr p(new int(3)); - BOOST_TEST(*p == 3); - } - //Array unique_ptr - { - int *pi = new int[2]; - pi[0] = 3; - pi[1] = 4; - bml::unique_ptr p(pi); - BOOST_TEST(p[0] == 3); - BOOST_TEST(p[1] == 4); - } -} - -} //namespace unique_ptr_observers_dereference{ - -//////////////////////////////// -// unique_ptr_observers_dereference -//////////////////////////////// - -namespace unique_ptr_observers_explicit_bool{ - -void test() -{ - //Single unique_ptr - { - bml::unique_ptr p(new int(3)); - if (p) - ; - else - BOOST_TEST(false); - if (!p) - BOOST_TEST(false); - } - { - bml::unique_ptr p; - if (!p) - ; - else - BOOST_TEST(false); - if (p) - BOOST_TEST(false); - } - //Array unique_ptr - { - bml::unique_ptr p(new int[2]); - if (p) - ; - else - BOOST_TEST(false); - if (!p) - BOOST_TEST(false); - } - { - bml::unique_ptr p; - if (!p) - ; - else - BOOST_TEST(false); - if (p) - BOOST_TEST(false); - } -} - -} //namespace unique_ptr_observers_explicit_bool{ - -//////////////////////////////// -// unique_ptr_observers_get -//////////////////////////////// - -namespace unique_ptr_observers_get{ - -void test() -{ - //Single unique_ptr - { - int* p = new int; - bml::unique_ptr s(p); - BOOST_TEST(s.get() == p); - } - //Array unique_ptr - { - int* p = new int[2]; - bml::unique_ptr s(p); - BOOST_TEST(s.get() == p); - } -} - -} //namespace unique_ptr_observers_get{ - -//////////////////////////////// -// unique_ptr_observers_get_deleter -//////////////////////////////// - -namespace unique_ptr_observers_get_deleter{ - -struct Deleter -{ - void operator()(void*) {} - - int test() {return 5;} - int test() const {return 6;} -}; - -void test() -{ - //Single unique_ptr - { - bml::unique_ptr p; - BOOST_TEST(p.get_deleter().test() == 5); - } - { - const bml::unique_ptr p; - BOOST_TEST(p.get_deleter().test() == 6); - } - //Array unique_ptr - { - bml::unique_ptr p; - BOOST_TEST(p.get_deleter().test() == 5); - } - { - const bml::unique_ptr p; - BOOST_TEST(p.get_deleter().test() == 6); - } -} - -} //namespace unique_ptr_observers_get_deleter{ - -//////////////////////////////// -// unique_ptr_observers_op_arrow -//////////////////////////////// - -namespace unique_ptr_observers_op_arrow{ - -void test() -{ - //Single unique_ptr - { - bml::unique_ptr p(new A); - BOOST_TEST(p->state_ == 999); - } -} - -} //namespace unique_ptr_observers_op_arrow{ - - -namespace unique_ptr_observers_op_index{ - -void test() -{ - //Single unique_ptr - { - A *pa = new A[2]; - //pa[0] is left default constructed - pa[1].set(888); - bml::unique_ptr p(pa); - BOOST_TEST(p[0].state_ == 999); - BOOST_TEST(p[1].state_ == 888); - } -} - -} //namespace unique_ptr_observers_op_index{ - -//////////////////////////////// -// unique_ptr_zero -//////////////////////////////// -namespace unique_ptr_zero { - -// test initialization/assignment from zero - -void test() -{ - //Single unique_ptr - reset_counters(); - { - bml::unique_ptr s2(0); - BOOST_TEST(A::count == 0); - } - BOOST_TEST(A::count == 0); - { - bml::unique_ptr s2(new A); - BOOST_TEST(A::count == 1); - s2 = 0; - BOOST_TEST(A::count == 0); - BOOST_TEST(s2.get() == 0); - } - BOOST_TEST(A::count == 0); - - //Array unique_ptr - { - bml::unique_ptr s2(0); - BOOST_TEST(A::count == 0); - } - BOOST_TEST(A::count == 0); - { - bml::unique_ptr s2(new A[2]); - BOOST_TEST(A::count == 2); - s2 = 0; - BOOST_TEST(A::count == 0); - BOOST_TEST(s2.get() == 0); - } - BOOST_TEST(A::count == 0); -} - -} //namespace unique_ptr_zero { - - -//////////////////////////////// -// unique_ptr_nullptr -//////////////////////////////// - -namespace unique_ptr_nullptr{ - -void test() -{ - #if !defined(BOOST_NO_CXX11_NULLPTR) - //Single unique_ptr - reset_counters(); - { - bml::unique_ptr p(new A); - BOOST_TEST(A::count == 1); - A* i = p.get(); - (void)i; - p.reset(nullptr); - BOOST_TEST(A::count == 0); - BOOST_TEST(p.get() == 0); - } - BOOST_TEST(A::count == 0); - { - bml::unique_ptr p(new A); - BOOST_TEST(A::count == 1); - A* i = p.get(); - (void)i; - p = nullptr; - BOOST_TEST(A::count == 0); - BOOST_TEST(p.get() == 0); - } - BOOST_TEST(A::count == 0); - - { - bml::unique_ptr pi(nullptr); - BOOST_TEST(pi.get() == nullptr); - BOOST_TEST(pi.get() == 0); - } - BOOST_TEST(A::count == 0); - { - bml::unique_ptr pi(nullptr, bml::unique_ptr::deleter_type()); - BOOST_TEST(pi.get() == nullptr); - BOOST_TEST(pi.get() == 0); - } - BOOST_TEST(A::count == 0); - - //Array unique_ptr - reset_counters(); - { - bml::unique_ptr p(new A[2]); - BOOST_TEST(A::count == 2); - A* i = p.get(); - (void)i; - p.reset(nullptr); - BOOST_TEST(A::count == 0); - BOOST_TEST(p.get() == 0); - } - BOOST_TEST(A::count == 0); - { - bml::unique_ptr p(new A[2]); - BOOST_TEST(A::count == 2); - A* i = p.get(); - (void)i; - p = nullptr; - BOOST_TEST(A::count == 0); - BOOST_TEST(p.get() == 0); - } - BOOST_TEST(A::count == 0); - { - bml::unique_ptr pi(nullptr); - BOOST_TEST(pi.get() == nullptr); - BOOST_TEST(pi.get() == 0); - } - BOOST_TEST(A::count == 0); - { - bml::unique_ptr pi(nullptr, bml::unique_ptr::deleter_type()); - BOOST_TEST(pi.get() == nullptr); - BOOST_TEST(pi.get() == 0); - } - BOOST_TEST(A::count == 0); - - //Array element - #endif -} - -} //namespace unique_ptr_nullptr{ - -//////////////////////////////// -// main -//////////////////////////////// -int main() -{ - //General - pointer_type::test(); - - //Assignment - unique_ptr_asgn_move_convert01::test(); - unique_ptr_asgn_move_convert02::test(); - unique_ptr_asgn_move_convert03::test(); - unique_ptr_asgn_move01::test(); - - //Constructor - unique_ptr_ctor_default01::test(); - unique_ptr_ctor_default02::test(); - unique_ptr_ctor_move_convert01::test(); - unique_ptr_ctor_move_convert02::test(); - unique_ptr_ctor_move_convert03::test(); - unique_ptr_ctor_move_convert04::test(); - unique_ptr_ctor_move_convert05::test(); - unique_ptr_ctor_move_convert06::test(); - unique_ptr_ctor_move01::test(); - unique_ptr_ctor_move02::test(); - unique_ptr_ctor_pointer_deleter01::test(); - unique_ptr_ctor_pointer_deleter02::test(); - unique_ptr_ctor_pointer_deleter03::test(); - unique_ptr_ctor_pointer_deleter04::test(); - unique_ptr_ctor_pointer_deleter05::test(); - unique_ptr_ctor_pointer_deleter06::test(); - unique_ptr_ctor_pointer01::test(); - unique_ptr_ctor_pointer02::test(); - unique_ptr_ctor_pointer03::test(); - - //Destructor - unique_ptr_dtor_null::test(); - - //Modifiers - unique_ptr_modifiers_release::test(); - unique_ptr_modifiers_reset1::test(); - unique_ptr_modifiers_reset2::test(); - unique_ptr_modifiers_swap::test(); - - //Observers - unique_ptr_observers_dereference::test(); - unique_ptr_observers_explicit_bool::test(); - unique_ptr_observers_get::test(); - unique_ptr_observers_get_deleter::test(); - unique_ptr_observers_op_arrow::test(); - unique_ptr_observers_op_index::test(); - - //nullptr - unique_ptr_zero::test(); - unique_ptr_nullptr::test(); - - //Test results - return boost::report_errors(); - -} - -//Define the incomplete I type and out of line functions - -struct I -{ - static int count; - I() {++count;} - I(const A&) {++count;} - ~I() {--count;} -}; - -int I::count = 0; - -I* get() {return new I;} -I* get_array(int i) {return new I[i];} - -void check(int i) -{ - BOOST_TEST(I::count == i); -} - -template -J::~J() {} - -void reset_counters() -{ A::count = 0; B::count = 0; I::count = 0; } diff --git a/test/unique_ptr_assign.cpp b/test/unique_ptr_assign.cpp new file mode 100644 index 0000000..088b7f4 --- /dev/null +++ b/test/unique_ptr_assign.cpp @@ -0,0 +1,444 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Howard Hinnant 2009 +// (C) Copyright Ion Gaztanaga 2014-2014. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/move for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include + +////////////////////////////////////////////// +// +// The initial implementation of these tests +// was written by Howard Hinnant. +// +// These test were later refactored grouping +// and porting them to Boost.Move. +// +// Many thanks to Howard for releasing his C++03 +// unique_ptr implementation with such detailed +// test cases. +// +////////////////////////////////////////////// + +#include "unique_ptr_test_utils_beg.hpp" + +namespace bml = ::boost::movelib; + +//////////////////////////////// +// unique_ptr_asgn_move_convert_defdel +//////////////////////////////// +namespace unique_ptr_asgn_move_convert_defdel { + +void test() +{ + //Single unique_ptr + reset_counters(); + { + bml::unique_ptr s(new B); + A* p = s.get(); + bml::unique_ptr s2(new A); + BOOST_TEST(A::count == 2); + s2 = boost::move(s); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 1); + BOOST_TEST(B::count == 1); + } + BOOST_TEST(A::count == 0); + BOOST_TEST(B::count == 0); + + //Unbounded array unique_ptr + reset_counters(); + { + bml::unique_ptr s(new A[2]); + A* p = s.get(); + bml::unique_ptr s2(new const A[2]); + BOOST_TEST(A::count == 4); + s2 = boost::move(s); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 2); + } + BOOST_TEST(A::count == 0); + //Bounded array unique_ptr + reset_counters(); + { + bml::unique_ptr s(new A[2]); + A* p = s.get(); + bml::unique_ptr s2(new const A[2]); + BOOST_TEST(A::count == 4); + s2 = boost::move(s); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 2); + } + { + BOOST_TEST(A::count == 0); + bml::unique_ptr s(new A[2]); + A* p = s.get(); + bml::unique_ptr s2(new const A[2]); + BOOST_TEST(A::count == 4); + s2 = boost::move(s); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 2); + } + BOOST_TEST(A::count == 0); +} + +} //namespace unique_ptr_asgn_move_convert_defdel{ + +//////////////////////////////// +// unique_ptr_asgn_move_convert_movdel +//////////////////////////////// + +namespace unique_ptr_asgn_move_convert_movedel{ + +void test() +{ + //Single unique_ptr + reset_counters(); + { + bml::unique_ptr > s(new B); + A* p = s.get(); + bml::unique_ptr > s2(new A); + BOOST_TEST(A::count == 2); + s2 = (boost::move(s)); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 1); + BOOST_TEST(B::count == 1); + BOOST_TEST(s2.get_deleter().state() == 5); + BOOST_TEST(s.get_deleter().state() == 0); + } + BOOST_TEST(A::count == 0); + BOOST_TEST(B::count == 0); + + //Unbounded array unique_ptr + reset_counters(); + { + bml::unique_ptr > s(new A[2]); + A* p = s.get(); + bml::unique_ptr > s2(new const A[2]); + BOOST_TEST(A::count == 4); + s2 = (boost::move(s)); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 2); + BOOST_TEST(s2.get_deleter().state() == 5); + BOOST_TEST(s.get_deleter().state() == 0); + } + BOOST_TEST(A::count == 0); + + //Bounded array unique_ptr + reset_counters(); + { + bml::unique_ptr > s(new A[3]); + A* p = s.get(); + bml::unique_ptr > s2(new const A[2]); + BOOST_TEST(A::count == 5); + s2 = (boost::move(s)); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 3); + BOOST_TEST(s2.get_deleter().state() == 5); + BOOST_TEST(s.get_deleter().state() == 0); + } + BOOST_TEST(A::count == 0); + reset_counters(); + { + bml::unique_ptr > s(new A[2]); + A* p = s.get(); + bml::unique_ptr > s2(new const A[2]); + BOOST_TEST(A::count == 4); + s2 = (boost::move(s)); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 2); + BOOST_TEST(s2.get_deleter().state() == 5); + BOOST_TEST(s.get_deleter().state() == 0); + } + BOOST_TEST(A::count == 0); +} + +} //namespace unique_ptr_asgn_move_convert_movedel{ + +//////////////////////////////// +// unique_ptr_asgn_move_convert_copydelref +//////////////////////////////// + +namespace unique_ptr_asgn_move_convert_copydelref{ + +// test converting move assignment with reference deleters + +void test() +{ + //Single unique_ptr + reset_counters(); + { + copy_constr_deleter db(5); + bml::unique_ptr&> s(new B, db); + A* p = s.get(); + copy_constr_deleter da(6); + bml::unique_ptr&> s2(new A, da); + s2 = boost::move(s); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 1); + BOOST_TEST(B::count == 1); + BOOST_TEST(s2.get_deleter().state() == 5); + } + BOOST_TEST(A::count == 0); + BOOST_TEST(B::count == 0); + + //Unbounded array unique_ptr + reset_counters(); + { + copy_constr_deleter db(5); + bml::unique_ptr&> s(new A[2], db); + A* p = s.get(); + copy_constr_deleter da(6); + bml::unique_ptr&> s2(new const A[2], da); + BOOST_TEST(A::count == 4); + s2 = boost::move(s); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 2); + BOOST_TEST(s2.get_deleter().state() == 5); + } + BOOST_TEST(A::count == 0); + + //Bounded array unique_ptr + reset_counters(); + { + copy_constr_deleter db(5); + bml::unique_ptr&> s(new A[2], db); + A* p = s.get(); + copy_constr_deleter da(6); + bml::unique_ptr&> s2(new const A[2], da); + BOOST_TEST(A::count == 4); + s2 = boost::move(s); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 2); + BOOST_TEST(s2.get_deleter().state() == 5); + } + BOOST_TEST(A::count == 0); + reset_counters(); + { + copy_constr_deleter db(5); + bml::unique_ptr&> s(new A[2], db); + A* p = s.get(); + copy_constr_deleter da(6); + bml::unique_ptr&> s2(new const A[2], da); + BOOST_TEST(A::count == 4); + s2 = boost::move(s); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 2); + BOOST_TEST(s2.get_deleter().state() == 5); + } + BOOST_TEST(A::count == 0); +} + +} //namespace unique_ptr_asgn_move_convert_copydelref{ + +//////////////////////////////// +// unique_ptr_asgn_move_defdel +//////////////////////////////// +namespace unique_ptr_asgn_move_defdel { + +void test() +{ + //Single unique_ptr + reset_counters(); + { + bml::unique_ptr s1(new A); + A* p = s1.get(); + bml::unique_ptr s2(new A); + BOOST_TEST(A::count == 2); + s2 = boost::move(s1); + BOOST_TEST(A::count == 1); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s1.get() == 0); + } + BOOST_TEST(A::count == 0); + + //Unbounded array unique_ptr + reset_counters(); + { + bml::unique_ptr s1(new A[2]); + A* p = s1.get(); + bml::unique_ptr s2(new A[2]); + BOOST_TEST(A::count == 4); + s2 = boost::move(s1); + BOOST_TEST(A::count == 2); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s1.get() == 0); + } + BOOST_TEST(A::count == 0); + //Bounded array unique_ptr + reset_counters(); + { + bml::unique_ptr s1(new A[2]); + A* p = s1.get(); + bml::unique_ptr s2(new A[2]); + BOOST_TEST(A::count == 4); + s2 = boost::move(s1); + BOOST_TEST(A::count == 2); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s1.get() == 0); + } + BOOST_TEST(A::count == 0); +} + +} //unique_ptr_asgn_move_defdel + +//////////////////////////////// +// unique_ptr_asgn_move_movedel +//////////////////////////////// +namespace unique_ptr_asgn_move_movedel { + +void test() +{ + //Single unique_ptr + reset_counters(); + { + bml::unique_ptr > s1(new A); + A* p = s1.get(); + bml::unique_ptr > s2(new A); + BOOST_TEST(A::count == 2); + s2 = boost::move(s1); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s1.get() == 0); + BOOST_TEST(A::count == 1); + BOOST_TEST(s2.get_deleter().state() == 5); + BOOST_TEST(s1.get_deleter().state() == 0); + } + BOOST_TEST(A::count == 0); + + //Unbounded array unique_ptr + reset_counters(); + { + bml::unique_ptr > s1(new A[2]); + A* p = s1.get(); + bml::unique_ptr > s2(new A[2]); + BOOST_TEST(A::count == 4); + s2 = boost::move(s1); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s1.get() == 0); + BOOST_TEST(A::count == 2); + BOOST_TEST(s2.get_deleter().state() == 5); + BOOST_TEST(s1.get_deleter().state() == 0); + } + BOOST_TEST(A::count == 0); + + BOOST_TEST(A::count == 0); + //Bounded array unique_ptr + reset_counters(); + { + bml::unique_ptr > s1(new A[2]); + A* p = s1.get(); + bml::unique_ptr > s2(new A[2]); + BOOST_TEST(A::count == 4); + s2 = boost::move(s1); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s1.get() == 0); + BOOST_TEST(A::count == 2); + BOOST_TEST(s2.get_deleter().state() == 5); + BOOST_TEST(s1.get_deleter().state() == 0); + } + BOOST_TEST(A::count == 0); +} + +} //unique_ptr_asgn_move_movedel + +//////////////////////////////// +// unique_ptr_asgn_move_copydelref +//////////////////////////////// +namespace unique_ptr_asgn_move_copydelref { + +void test() +{ + //Single unique_ptr + reset_counters(); + { + copy_constr_deleter d1(5); + bml::unique_ptr&> s1(new A, d1); + A* p = s1.get(); + copy_constr_deleter d2(6); + bml::unique_ptr&> s2(new A, d2); + s2 = boost::move(s1); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s1.get() == 0); + BOOST_TEST(A::count == 1); + BOOST_TEST(d1.state() == 5); + BOOST_TEST(d2.state() == 5); + } + BOOST_TEST(A::count == 0); + + //Unbounded array unique_ptr + reset_counters(); + { + copy_constr_deleter d1(5); + bml::unique_ptr&> s1(new A[2], d1); + A* p = s1.get(); + copy_constr_deleter d2(6); + bml::unique_ptr&> s2(new A[2], d2); + BOOST_TEST(A::count == 4); + s2 = boost::move(s1); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s1.get() == 0); + BOOST_TEST(A::count == 2); + BOOST_TEST(d1.state() == 5); + BOOST_TEST(d2.state() == 5); + } + BOOST_TEST(A::count == 0); + //Bounded array unique_ptr + reset_counters(); + { + copy_constr_deleter d1(5); + bml::unique_ptr&> s1(new A[2], d1); + A* p = s1.get(); + copy_constr_deleter d2(6); + bml::unique_ptr&> s2(new A[2], d2); + BOOST_TEST(A::count == 4); + s2 = boost::move(s1); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s1.get() == 0); + BOOST_TEST(A::count == 2); + BOOST_TEST(d1.state() == 5); + BOOST_TEST(d2.state() == 5); + } + BOOST_TEST(A::count == 0); +} + +} //unique_ptr_asgn_move_copydelref + +//////////////////////////////// +// main +//////////////////////////////// +int main() +{ + //Assignment + unique_ptr_asgn_move_convert_defdel::test(); + unique_ptr_asgn_move_convert_movedel::test(); + unique_ptr_asgn_move_convert_copydelref::test(); + unique_ptr_asgn_move_defdel::test(); + unique_ptr_asgn_move_movedel::test(); + unique_ptr_asgn_move_copydelref::test(); + + //Test results + return boost::report_errors(); +} + +#include "unique_ptr_test_utils_end.hpp" diff --git a/test/unique_ptr_ctordtor.cpp b/test/unique_ptr_ctordtor.cpp new file mode 100644 index 0000000..1225507 --- /dev/null +++ b/test/unique_ptr_ctordtor.cpp @@ -0,0 +1,708 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Howard Hinnant 2009 +// (C) Copyright Ion Gaztanaga 2014-2014. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/move for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include + +////////////////////////////////////////////// +// +// The initial implementation of these tests +// was written by Howard Hinnant. +// +// These test were later refactored grouping +// and porting them to Boost.Move. +// +// Many thanks to Howard for releasing his C++03 +// unique_ptr implementation with such detailed +// test cases. +// +////////////////////////////////////////////// + +#include "unique_ptr_test_utils_beg.hpp" + +namespace bml = ::boost::movelib; + +//////////////////////////////// +// unique_ptr_dtor_null +//////////////////////////////// + +namespace unique_ptr_dtor_null{ + +// The deleter is not called if get() == 0 + +void test() +{ + //Single unique_ptr + { + def_constr_deleter d; + BOOST_TEST(d.state() == 5); + { + bml::unique_ptr&> p(0, d); + BOOST_TEST(p.get() == 0); + BOOST_TEST(&p.get_deleter() == &d); + } + BOOST_TEST(d.state() == 5); + } + { + //Unbounded array unique_ptr + def_constr_deleter d; + BOOST_TEST(d.state() == 5); + { + bml::unique_ptr&> p(0, d); + BOOST_TEST(p.get() == 0); + BOOST_TEST(&p.get_deleter() == &d); + } + BOOST_TEST(d.state() == 5); + } + { + //Bounded array unique_ptr + def_constr_deleter d; + BOOST_TEST(d.state() == 5); + { + bml::unique_ptr&> p(0, d); + BOOST_TEST(p.get() == 0); + BOOST_TEST(&p.get_deleter() == &d); + } + BOOST_TEST(d.state() == 5); + } +} + +} //namespace unique_ptr_dtor_null{ + +//////////////////////////////// +// unique_ptr_ctor_default_delreq +//////////////////////////////// + +namespace unique_ptr_ctor_default_delreq{ + +// default unique_ptr ctor should only require default deleter ctor + +void test() +{ + //Single unique_ptr + { + bml::unique_ptr p; + BOOST_TEST(p.get() == 0); + } + { + bml::unique_ptr > p; + BOOST_TEST(p.get() == 0); + BOOST_TEST(p.get_deleter().state() == 5); + } + //Unbounded array unique_ptr + { + bml::unique_ptr p; + BOOST_TEST(p.get() == 0); + } + { + bml::unique_ptr > p; + BOOST_TEST(p.get() == 0); + BOOST_TEST(p.get_deleter().state() == 5); + } + + //Unbounded array unique_ptr + { + bml::unique_ptr p; + BOOST_TEST(p.get() == 0); + } + { + bml::unique_ptr > p; + BOOST_TEST(p.get() == 0); + BOOST_TEST(p.get_deleter().state() == 5); + } + + //Unbounded array unique_ptr + { + bml::unique_ptr p; + BOOST_TEST(p.get() == 0); + } + { + bml::unique_ptr > p; + BOOST_TEST(p.get() == 0); + BOOST_TEST(p.get_deleter().state() == 5); + } +} + +} //namespace unique_ptr_ctor_default_delreq{ + +//////////////////////////////// +// unique_ptr_ctor_default_nocomplete +//////////////////////////////// + +namespace unique_ptr_ctor_default_nocomplete{ + +// default unique_ptr ctor shouldn't require complete type + +void test() +{ + //Single unique_ptr + reset_counters(); + { + J s; + BOOST_TEST(s.get() == 0); + } + check(0); + { + J > s; + BOOST_TEST(s.get() == 0); + BOOST_TEST(s.get_deleter().state() == 5); + } + check(0); + //Unbounded array unique_ptr + reset_counters(); + { + J s; + BOOST_TEST(s.get() == 0); + } + check(0); + { + J > s; + BOOST_TEST(s.get() == 0); + BOOST_TEST(s.get_deleter().state() == 5); + } + check(0); + + //Bounded array unique_ptr + reset_counters(); + { + J s; + BOOST_TEST(s.get() == 0); + } + check(0); + { + J > s; + BOOST_TEST(s.get() == 0); + BOOST_TEST(s.get_deleter().state() == 5); + } + check(0); +} + +} //namespace unique_ptr_ctor_default_nocomplete{ + +//////////////////////////////// +// unique_ptr_ctor_pointer_delreq +//////////////////////////////// + +namespace unique_ptr_ctor_pointer_delreq{ + +// unique_ptr(pointer) ctor should only require default deleter ctor + +void test() +{ + //Single unique_ptr + reset_counters(); + { + A* p = new A; + BOOST_TEST(A::count == 1); + bml::unique_ptr s(p); + BOOST_TEST(s.get() == p); + } + BOOST_TEST(A::count == 0); + { + A* p = new A; + BOOST_TEST(A::count == 1); + bml::unique_ptr > s(p); + BOOST_TEST(s.get() == p); + BOOST_TEST(s.get_deleter().state() == 5); + } + BOOST_TEST(A::count == 0); + //Unbounded array unique_ptr + reset_counters(); + { + A* p = new A[2]; + BOOST_TEST(A::count == 2); + bml::unique_ptr s(p); + BOOST_TEST(s.get() == p); + } + BOOST_TEST(A::count == 0); + { + A* p = new A[2]; + BOOST_TEST(A::count == 2); + bml::unique_ptr > s(p); + BOOST_TEST(s.get() == p); + BOOST_TEST(s.get_deleter().state() == 5); + } + BOOST_TEST(A::count == 0); + //Bounded array unique_ptr + reset_counters(); + { + A* p = new A[2]; + BOOST_TEST(A::count == 2); + bml::unique_ptr s(p); + BOOST_TEST(s.get() == p); + } + BOOST_TEST(A::count == 0); + { + A* p = new A[2]; + BOOST_TEST(A::count == 2); + bml::unique_ptr > s(p); + BOOST_TEST(s.get() == p); + BOOST_TEST(s.get_deleter().state() == 5); + } + BOOST_TEST(A::count == 0); +} + +} //namespace unique_ptr_ctor_pointer_delreq{ + +//////////////////////////////// +// unique_ptr_ctor_pointer_nocomplete +//////////////////////////////// + +namespace unique_ptr_ctor_pointer_nocomplete{ + +// unique_ptr(pointer) ctor shouldn't require complete type + +void test() +{ + //Single unique_ptr + reset_counters(); + { + I* p = get(); + check(1); + J s(p); + BOOST_TEST(s.get() == p); + } + check(0); + { + I* p = get(); + check(1); + J > s(p); + BOOST_TEST(s.get() == p); + BOOST_TEST(s.get_deleter().state() == 5); + } + check(0); + //Unbounded array unique_ptr + reset_counters(); + { + I* p = get_array(2); + check(2); + J s(p); + BOOST_TEST(s.get() == p); + } + check(0); + { + I* p = get_array(2); + check(2); + J > s(p); + BOOST_TEST(s.get() == p); + BOOST_TEST(s.get_deleter().state() == 5); + } + check(0); + //Bounded array unique_ptr + reset_counters(); + { + I* p = get_array(2); + check(2); + J s(p); + BOOST_TEST(s.get() == p); + } + check(0); + { + I* p = get_array(2); + check(2); + J > s(p); + BOOST_TEST(s.get() == p); + BOOST_TEST(s.get_deleter().state() == 5); + } + check(0); +} + +} //namespace unique_ptr_ctor_pointer_nocomplete{ + +//////////////////////////////// +// unique_ptr_ctor_pointer_convert +//////////////////////////////// + +namespace unique_ptr_ctor_pointer_convert{ + +// unique_ptr(pointer) ctor should work with derived pointers +// or same types (cv aside) for unique_ptr + +void test() +{ + //Single unique_ptr + reset_counters(); + { + B* p = new B; + BOOST_TEST(A::count == 1); + BOOST_TEST(B::count == 1); + bml::unique_ptr s(p); + BOOST_TEST(s.get() == p); + } + BOOST_TEST(A::count == 0); + BOOST_TEST(B::count == 0); + { + B* p = new B; + BOOST_TEST(A::count == 1); + BOOST_TEST(B::count == 1); + bml::unique_ptr > s(p); + BOOST_TEST(s.get() == p); + BOOST_TEST(s.get_deleter().state() == 5); + } + BOOST_TEST(A::count == 0); + BOOST_TEST(B::count == 0); + //Unbounded array unique_ptr + reset_counters(); + { + A* p = new A[2]; + BOOST_TEST(A::count == 2); + bml::unique_ptr s(p); + BOOST_TEST(s.get() == p); + } + BOOST_TEST(A::count == 0); + { + const A* p = new const A[2]; + BOOST_TEST(A::count == 2); + bml::unique_ptr > s(p); + BOOST_TEST(s.get() == p); + BOOST_TEST(s.get_deleter().state() == 5); + } + BOOST_TEST(A::count == 0); + //Bounded array unique_ptr + reset_counters(); + { + A* p = new A[2]; + BOOST_TEST(A::count == 2); + bml::unique_ptr s(p); + BOOST_TEST(s.get() == p); + } + BOOST_TEST(A::count == 0); + { + const A* p = new const A[2]; + BOOST_TEST(A::count == 2); + bml::unique_ptr > s(p); + BOOST_TEST(s.get() == p); + BOOST_TEST(s.get_deleter().state() == 5); + } + BOOST_TEST(A::count == 0); +} + +} //namespace unique_ptr_ctor_pointer_convert{ + +//////////////////////////////// +// unique_ptr_ctor_pointer_deleter_movedel +//////////////////////////////// + +namespace unique_ptr_ctor_pointer_deleter_movedel{ + +// test move ctor. Should only require a MoveConstructible deleter, or if +// deleter is a reference, not even that. + +// unique_ptr(pointer, deleter()) only requires MoveConstructible deleter + +void test() +{ + //Single unique_ptr + reset_counters(); + { + A* p = new A; + BOOST_TEST(A::count == 1); + move_constr_deleter d; + bml::unique_ptr > s(p, ::boost::move(d)); + BOOST_TEST(s.get() == p); + BOOST_TEST(s.get_deleter().state() == 5); + bml::unique_ptr > s2(s.release(), move_constr_deleter(6)); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s2.get_deleter().state() == 6); + } + BOOST_TEST(A::count == 0); + //Unbounded array unique_ptr + reset_counters(); + { + A* p = new A[2]; + BOOST_TEST(A::count == 2); + move_constr_deleter d; + bml::unique_ptr > s(p, ::boost::move(d)); + BOOST_TEST(s.get() == p); + BOOST_TEST(s.get_deleter().state() == 5); + bml::unique_ptr > s2(s.release(), move_constr_deleter(6)); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s2.get_deleter().state() == 6); + } + BOOST_TEST(A::count == 0); + //Bounded array unique_ptr + reset_counters(); + { + A* p = new A[2]; + BOOST_TEST(A::count == 2); + move_constr_deleter d; + bml::unique_ptr > s(p, ::boost::move(d)); + BOOST_TEST(s.get() == p); + BOOST_TEST(s.get_deleter().state() == 5); + bml::unique_ptr > s2(s.release(), move_constr_deleter(6)); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s2.get_deleter().state() == 6); + } + BOOST_TEST(A::count == 0); +} + +} //namespace unique_ptr_ctor_pointer_deleter_movedel{ + +//////////////////////////////// +// unique_ptr_ctor_pointer_deleter_copydel +//////////////////////////////// + +namespace unique_ptr_ctor_pointer_deleter_copydel{ + +// unique_ptr(pointer, d) requires CopyConstructible deleter + +void test() +{ + //Single unique_ptr + reset_counters(); + { + A* p = new A; + BOOST_TEST(A::count == 1); + copy_constr_deleter d; + bml::unique_ptr > s(p, d); + BOOST_TEST(s.get() == p); + BOOST_TEST(s.get_deleter().state() == 5); + d.set_state(6); + BOOST_TEST(s.get_deleter().state() == 5); + } + BOOST_TEST(A::count == 0); + //Unbounded array unique_ptr + reset_counters(); + { + A* p = new A[2]; + BOOST_TEST(A::count == 2); + copy_constr_deleter d; + bml::unique_ptr > s(p, d); + BOOST_TEST(s.get() == p); + BOOST_TEST(s.get_deleter().state() == 5); + d.set_state(6); + BOOST_TEST(s.get_deleter().state() == 5); + } + BOOST_TEST(A::count == 0); + //Bounded array unique_ptr + reset_counters(); + { + A* p = new A[2]; + BOOST_TEST(A::count == 2); + copy_constr_deleter d; + bml::unique_ptr > s(p, d); + BOOST_TEST(s.get() == p); + BOOST_TEST(s.get_deleter().state() == 5); + d.set_state(6); + BOOST_TEST(s.get_deleter().state() == 5); + } + BOOST_TEST(A::count == 0); +} + +} //namespace unique_ptr_ctor_pointer_deleter_copydel{ + +//////////////////////////////// +// unique_ptr_ctor_pointer_deleter_dfctrdelref +//////////////////////////////// + +namespace unique_ptr_ctor_pointer_deleter_dfctrdelref{ + +// unique_ptr(pointer, d) does not requires CopyConstructible deleter + +void test() +{ + //Single unique_ptr + reset_counters(); + { + A* p = new A; + BOOST_TEST(A::count == 1); + def_constr_deleter d; + bml::unique_ptr&> s(p, d); + BOOST_TEST(s.get() == p); + BOOST_TEST(s.get_deleter().state() == 5); + d.set_state(6); + BOOST_TEST(s.get_deleter().state() == 6); + } + BOOST_TEST(A::count == 0); + //Unbounded array unique_ptr + reset_counters(); + { + A* p = new A[2]; + BOOST_TEST(A::count == 2); + def_constr_deleter d; + bml::unique_ptr&> s(p, d); + BOOST_TEST(s.get() == p); + BOOST_TEST(s.get_deleter().state() == 5); + d.set_state(6); + BOOST_TEST(s.get_deleter().state() == 6); + } + BOOST_TEST(A::count == 0); + //Bounded array unique_ptr + reset_counters(); + { + A* p = new A[2]; + BOOST_TEST(A::count == 2); + def_constr_deleter d; + bml::unique_ptr&> s(p, d); + BOOST_TEST(s.get() == p); + BOOST_TEST(s.get_deleter().state() == 5); + d.set_state(6); + BOOST_TEST(s.get_deleter().state() == 6); + } + BOOST_TEST(A::count == 0); +} + +} //namespace unique_ptr_ctor_pointer_deleter_dfctrdelref{ + +//////////////////////////////// +// unique_ptr_ctor_pointer_deleter_dfctrdelconstref +//////////////////////////////// + +namespace unique_ptr_ctor_pointer_deleter_dfctrdelconstref{ + +// unique_ptr(pointer, d) does not requires CopyConstructible deleter + +void test() +{ + //Single unique_ptr + reset_counters(); + { + A* p = new A; + BOOST_TEST(A::count == 1); + def_constr_deleter d; + bml::unique_ptr&> s(p, d); + BOOST_TEST(s.get() == p); + BOOST_TEST(s.get_deleter().state() == 5); + } + BOOST_TEST(A::count == 0); + //Unbounded array unique_ptr + reset_counters(); + { + A* p = new A[2]; + BOOST_TEST(A::count == 2); + def_constr_deleter d; + bml::unique_ptr&> s(p, d); + BOOST_TEST(s.get() == p); + BOOST_TEST(s.get_deleter().state() == 5); + } + BOOST_TEST(A::count == 0); + //Bounded array unique_ptr + reset_counters(); + { + A* p = new A[2]; + BOOST_TEST(A::count == 2); + def_constr_deleter d; + bml::unique_ptr&> s(p, d); + BOOST_TEST(s.get() == p); + BOOST_TEST(s.get_deleter().state() == 5); + } + BOOST_TEST(A::count == 0); +} + +} //namespace unique_ptr_ctor_pointer_deleter_dfctrdelconstref{ + +//////////////////////////////// +// unique_ptr_ctor_pointer_deleter_convert +//////////////////////////////// + +namespace unique_ptr_ctor_pointer_deleter_convert{ + +// unique_ptr(pointer, deleter) should work with derived pointers +// or same (cv aside) types for array unique_ptrs + +void test() +{ + //Single unique_ptr + reset_counters(); + { + B* p = new B; + BOOST_TEST(A::count == 1); + BOOST_TEST(B::count == 1); + bml::unique_ptr > s(p, copy_constr_deleter()); + BOOST_TEST(s.get() == p); + BOOST_TEST(s.get_deleter().state() == 5); + } + BOOST_TEST(A::count == 0); + BOOST_TEST(B::count == 0); + //Unbounded array unique_ptr + reset_counters(); + { + A* p = new A[2]; + BOOST_TEST(A::count == 2); + bml::unique_ptr > s(p, copy_constr_deleter()); + BOOST_TEST(s.get() == p); + BOOST_TEST(s.get_deleter().state() == 5); + } + BOOST_TEST(A::count == 0); + BOOST_TEST(B::count == 0); + //Bounded array unique_ptr + reset_counters(); + { + A* p = new A[2]; + BOOST_TEST(A::count == 2); + bml::unique_ptr > s(p, copy_constr_deleter()); + BOOST_TEST(s.get() == p); + BOOST_TEST(s.get_deleter().state() == 5); + } + BOOST_TEST(A::count == 0); + BOOST_TEST(B::count == 0); +} + +} //namespace unique_ptr_ctor_pointer_deleter_convert{ + +//////////////////////////////// +// unique_ptr_ctor_pointer_deleter_void +//////////////////////////////// + +namespace unique_ptr_ctor_pointer_deleter_void{ + +// unique_ptr(pointer, deleter) should work with function pointers +// unique_ptr should work + +bool my_free_called = false; + +void my_free(void*) +{ + my_free_called = true; +} + +void test() +{ + { + int i = 0; + bml::unique_ptr s(&i, my_free); + BOOST_TEST(s.get() == &i); + BOOST_TEST(s.get_deleter() == my_free); + BOOST_TEST(!my_free_called); + } + BOOST_TEST(my_free_called); +} + +} //namespace unique_ptr_ctor_pointer_deleter_void{ + +//////////////////////////////// +// main +//////////////////////////////// +int main() +{ + //Constructors/Destructor + unique_ptr_dtor_null::test(); + unique_ptr_ctor_default_delreq::test(); + unique_ptr_ctor_default_nocomplete::test(); + unique_ptr_ctor_pointer_delreq::test(); + unique_ptr_ctor_pointer_nocomplete::test(); + unique_ptr_ctor_pointer_convert::test(); + unique_ptr_ctor_pointer_deleter_movedel::test(); + unique_ptr_ctor_pointer_deleter_copydel::test(); + unique_ptr_ctor_pointer_deleter_dfctrdelref::test(); + unique_ptr_ctor_pointer_deleter_dfctrdelconstref::test(); + unique_ptr_ctor_pointer_deleter_convert::test(); + unique_ptr_ctor_pointer_deleter_void::test(); + + //Test results + return boost::report_errors(); + +} + +#include "unique_ptr_test_utils_end.hpp" diff --git a/test/unique_ptr_default_deleter.cpp b/test/unique_ptr_default_deleter.cpp index 94103f3..cbe6255 100644 --- a/test/unique_ptr_default_deleter.cpp +++ b/test/unique_ptr_default_deleter.cpp @@ -83,10 +83,73 @@ void test() d1(p); BOOST_TEST(A::count == 0); } + //Bounded array element deleter + { + reset_counters(); + bml::default_delete d2; + bml::default_delete d1 = d2; + const A* p = new const A[2]; + BOOST_TEST(A::count == 2); + d1(p); + bml::default_delete d0 = d1; + d0(0); + BOOST_TEST(A::count == 0); + } } } //namespace unique_ptr_dltr_dflt_convert_ctor{ +//////////////////////////////// +// unique_ptr_dltr_dflt_convert_assign +//////////////////////////////// + +namespace unique_ptr_dltr_dflt_convert_assign{ + +void test() +{ + //Single element deleter + { + reset_counters(); + bml::default_delete d2; + bml::default_delete d1; + d1 = d2; + A* p = new B; + BOOST_TEST(A::count == 1); + BOOST_TEST(B::count == 1); + d1(p); + BOOST_TEST(A::count == 0); + BOOST_TEST(B::count == 0); + } + //Array element deleter + { + reset_counters(); + bml::default_delete d2; + bml::default_delete d1; + d1 = d2; + const A* p = new const A[2]; + BOOST_TEST(A::count == 2); + d1(p); + BOOST_TEST(A::count == 0); + } + //Bounded array element deleter + { + reset_counters(); + bml::default_delete d2; + bml::default_delete d1; + d1 = d2; + const A* p = new const A[2]; + BOOST_TEST(A::count == 2); + d1(p); + bml::default_delete d0; + d0 = d1; + d0(0); + BOOST_TEST(A::count == 0); + } +} + +} //namespace unique_ptr_dltr_dflt_convert_assign{ + + //////////////////////////////// // unique_ptr_dltr_dflt_default //////////////////////////////// @@ -113,6 +176,16 @@ void test() d(p); BOOST_TEST(A::count == 0); } + + { + //Bounded Array element deleter + reset_counters(); + bml::default_delete d; + A* p = new A[10]; + BOOST_TEST(A::count == 10); + d(p); + BOOST_TEST(A::count == 0); + } } } //namespace unique_ptr_dltr_dflt_default{ @@ -123,6 +196,7 @@ void test() int main() { unique_ptr_dltr_dflt_convert_ctor::test(); + unique_ptr_dltr_dflt_convert_assign::test(); unique_ptr_dltr_dflt_default::test(); //Test results diff --git a/test/unique_ptr_functions.cpp b/test/unique_ptr_functions.cpp index d730809..d8cdf9e 100644 --- a/test/unique_ptr_functions.cpp +++ b/test/unique_ptr_functions.cpp @@ -11,6 +11,7 @@ ////////////////////////////////////////////////////////////////////////////// #include #include +#include struct A { @@ -40,6 +41,27 @@ int B::count = 0; void reset_counters() { A::count = B::count = 0; } +static const unsigned PatternSize = 8; +static const unsigned char ff_patternbuf[PatternSize] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; +static const unsigned char ee_patternbuf[PatternSize] = { 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE }; + +struct default_init +{ + static void* operator new(std::size_t sz) + { + void *const p = ::operator new(sz); + return std::memset(p, 0xFF, sz); + } + static void* operator new[](std::size_t sz) + { + void *const p = ::operator new[](sz); + return std::memset(p, 0xEE, sz); + } + unsigned char buf[PatternSize]; +}; + + + namespace bml = ::boost::movelib; //////////////////////////////// @@ -53,12 +75,18 @@ void test() //Single element deleter reset_counters(); { + bml::unique_ptr p(bml::make_unique_definit()); + BOOST_TEST(0 == std::memcmp(p.get(), ff_patternbuf, sizeof(ff_patternbuf))); + } + BOOST_TEST(A::count == 0); + { bml::unique_ptr p(bml::make_unique()); BOOST_TEST(A::count == 1); BOOST_TEST(p->a == 999); BOOST_TEST(p->b == 1000); BOOST_TEST(p->c == 1001); } + BOOST_TEST(A::count == 0); { bml::unique_ptr p(bml::make_unique(0)); BOOST_TEST(A::count == 1); @@ -95,7 +123,7 @@ namespace make_unique_array{ void test() { - //Single element deleter + //Array element reset_counters(); { bml::unique_ptr p(bml::make_unique(10)); @@ -107,6 +135,13 @@ void test() } } BOOST_TEST(A::count == 0); + reset_counters(); + { + bml::unique_ptr p(bml::make_unique_definit(10)); + for(unsigned i = 0; i != 10; ++i){ + BOOST_TEST(0 == std::memcmp(&p[i], ee_patternbuf, sizeof(ee_patternbuf))); + } + } } } //namespace make_unique_array{ @@ -158,7 +193,6 @@ void test() } //namespace unique_compare{ - //////////////////////////////// // unique_compare_zero //////////////////////////////// diff --git a/test/unique_ptr_modifiers.cpp b/test/unique_ptr_modifiers.cpp new file mode 100644 index 0000000..b67d4f5 --- /dev/null +++ b/test/unique_ptr_modifiers.cpp @@ -0,0 +1,377 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Howard Hinnant 2009 +// (C) Copyright Ion Gaztanaga 2014-2014. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/move for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include + +////////////////////////////////////////////// +// +// The initial implementation of these tests +// was written by Howard Hinnant. +// +// These test were later refactored grouping +// and porting them to Boost.Move. +// +// Many thanks to Howard for releasing his C++03 +// unique_ptr implementation with such detailed +// test cases. +// +////////////////////////////////////////////// + +#include "unique_ptr_test_utils_beg.hpp" + +namespace bml = ::boost::movelib; + +//////////////////////////////// +// unique_ptr_modifiers_release +//////////////////////////////// + +namespace unique_ptr_modifiers_release{ + +void test() +{ + //Single unique_ptr + { + bml::unique_ptr p(new int(3)); + int* i = p.get(); + int* j = p.release(); + BOOST_TEST(p.get() == 0); + BOOST_TEST(i == j); + } + //Unbounded array unique_ptr + { + bml::unique_ptr p(new int[2]); + int* i = p.get(); + int* j = p.release(); + BOOST_TEST(p.get() == 0); + BOOST_TEST(i == j); + } + //Bounded array unique_ptr + { + bml::unique_ptr p(new int[2]); + int* i = p.get(); + int* j = p.release(); + BOOST_TEST(p.get() == 0); + BOOST_TEST(i == j); + } +} + +} //namespace unique_ptr_modifiers_release{ + +//////////////////////////////// +// unique_ptr_modifiers_reset +//////////////////////////////// + +namespace unique_ptr_modifiers_reset{ + +void test() +{ + //Single unique_ptr + { + reset_counters(); + { //reset() + bml::unique_ptr p(new A); + BOOST_TEST(A::count == 1); + A* i = p.get(); + (void)i; + p.reset(); + BOOST_TEST(A::count == 0); + BOOST_TEST(p.get() == 0); + } + BOOST_TEST(A::count == 0); + { //reset(p) + bml::unique_ptr p(new A); + BOOST_TEST(A::count == 1); + A* i = p.get(); + (void)i; + p.reset(new A); + BOOST_TEST(A::count == 1); + } + BOOST_TEST(A::count == 0); + { //reset(0) + bml::unique_ptr p(new A); + BOOST_TEST(A::count == 1); + A* i = p.get(); + (void)i; + p.reset(0); + BOOST_TEST(A::count == 0); + BOOST_TEST(p.get() == 0); + } + BOOST_TEST(A::count == 0); + } + //Unbounded array unique_ptr + { + reset_counters(); + { //reset() + bml::unique_ptr p(new A[2]); + BOOST_TEST(A::count == 2); + A* i = p.get(); + (void)i; + p.reset(); + BOOST_TEST(A::count == 0); + BOOST_TEST(p.get() == 0); + } + BOOST_TEST(A::count == 0); + { //reset(p) + bml::unique_ptr p(new A[2]); + BOOST_TEST(A::count == 2); + A* i = p.get(); + (void)i; + p.reset(new A[3]); + BOOST_TEST(A::count == 3); + } + BOOST_TEST(A::count == 0); + { //reset(0) + bml::unique_ptr p(new A[2]); + BOOST_TEST(A::count == 2); + A* i = p.get(); + (void)i; + p.reset(0); + BOOST_TEST(A::count == 0); + BOOST_TEST(p.get() == 0); + } + BOOST_TEST(A::count == 0); + } + { + //Bounded array unique_ptr + reset_counters(); + { //reset() + bml::unique_ptr p(new A[2]); + BOOST_TEST(A::count == 2); + A* i = p.get(); + (void)i; + p.reset(); + BOOST_TEST(A::count == 0); + BOOST_TEST(p.get() == 0); + } + BOOST_TEST(A::count == 0); + { //reset(p) + bml::unique_ptr p(new A[2]); + BOOST_TEST(A::count == 2); + A* i = p.get(); + (void)i; + p.reset(new A[3]); + BOOST_TEST(A::count == 3); + } + BOOST_TEST(A::count == 0); + { //reset(0) + bml::unique_ptr p(new A[2]); + BOOST_TEST(A::count == 2); + A* i = p.get(); + (void)i; + p.reset(0); + BOOST_TEST(A::count == 0); + BOOST_TEST(p.get() == 0); + } + BOOST_TEST(A::count == 0); + } +} + +} //namespace unique_ptr_modifiers_reset{ + +//////////////////////////////// +// unique_ptr_modifiers_reset_convert +//////////////////////////////// + +namespace unique_ptr_modifiers_reset_convert{ + +void test() +{ + //Single unique_ptr + reset_counters(); + { + bml::unique_ptr p(new A); + BOOST_TEST(A::count == 1); + BOOST_TEST(B::count == 0); + A* i = p.get(); + (void)i; + p.reset(new B); + BOOST_TEST(A::count == 1); + BOOST_TEST(B::count == 1); + } + BOOST_TEST(A::count == 0); + BOOST_TEST(B::count == 0); + { + bml::unique_ptr p(new B); + BOOST_TEST(A::count == 1); + BOOST_TEST(B::count == 1); + A* i = p.get(); + (void)i; + p.reset(new B); + BOOST_TEST(A::count == 1); + BOOST_TEST(B::count == 1); + } + BOOST_TEST(A::count == 0); + BOOST_TEST(B::count == 0); + //Unbounded array unique_ptr + reset_counters(); + { + bml::unique_ptr p(new const A[2]); + BOOST_TEST(A::count == 2); + const volatile A* i = p.get(); + (void)i; + p.reset(new volatile A[3]); + BOOST_TEST(A::count == 3); + } + BOOST_TEST(A::count == 0); + { + bml::unique_ptr p(new A[2]); + BOOST_TEST(A::count == 2); + const A* i = p.get(); + (void)i; + p.reset(new const A[3]); + BOOST_TEST(A::count == 3); + } + BOOST_TEST(A::count == 0); + //Bounded array unique_ptr + reset_counters(); + { + bml::unique_ptr p(new const A[2]); + BOOST_TEST(A::count == 2); + const volatile A* i = p.get(); + (void)i; + p.reset(new volatile A[3]); + BOOST_TEST(A::count == 3); + } + BOOST_TEST(A::count == 0); + { + bml::unique_ptr p(new A[2]); + BOOST_TEST(A::count == 2); + const A* i = p.get(); + (void)i; + p.reset(new const A[3]); + BOOST_TEST(A::count == 3); + } + BOOST_TEST(A::count == 0); +} + +} //unique_ptr_modifiers_reset_convert + + +//////////////////////////////// +// unique_ptr_modifiers +//////////////////////////////// + +namespace unique_ptr_modifiers_swap{ + +// test swap + +void test() +{ + //Single unique_ptr + reset_counters(); + { + A* p1 = new A(1); + move_constr_deleter d1(1); + bml::unique_ptr > s1(p1, ::boost::move(d1)); + A* p2 = new A(2); + move_constr_deleter d2(2); + bml::unique_ptr > s2(p2, ::boost::move(d2)); + BOOST_TEST(s1.get() == p1); + BOOST_TEST(*s1 == A(1)); + BOOST_TEST(s1.get_deleter().state() == 1); + BOOST_TEST(s2.get() == p2); + BOOST_TEST(*s2 == A(2)); + BOOST_TEST(s2.get_deleter().state() == 2); + swap(s1, s2); + BOOST_TEST(s1.get() == p2); + BOOST_TEST(*s1 == A(2)); + BOOST_TEST(s1.get_deleter().state() == 2); + BOOST_TEST(s2.get() == p1); + BOOST_TEST(*s2 == A(1)); + BOOST_TEST(s2.get_deleter().state() == 1); + } + //Unbounded array unique_ptr + reset_counters(); + { + A* p1 = new A[2]; + p1[0].set(1); + p1[1].set(2); + move_constr_deleter d1(1); + bml::unique_ptr > s1(p1, ::boost::move(d1)); + A* p2 = new A[2]; + p2[0].set(3); + p2[1].set(4); + move_constr_deleter d2(2); + bml::unique_ptr > s2(p2, ::boost::move(d2)); + BOOST_TEST(s1.get() == p1); + BOOST_TEST(s1[0] == A(1)); + BOOST_TEST(s1[1] == A(2)); + BOOST_TEST(s1.get_deleter().state() == 1); + BOOST_TEST(s2.get() == p2); + BOOST_TEST(s2[0] == A(3)); + BOOST_TEST(s2[1] == A(4)); + BOOST_TEST(s2.get_deleter().state() == 2); + swap(s1, s2); + BOOST_TEST(s1.get() == p2); + BOOST_TEST(s1[0] == A(3)); + BOOST_TEST(s1[1] == A(4)); + BOOST_TEST(s1.get_deleter().state() == 2); + BOOST_TEST(s2.get() == p1); + BOOST_TEST(s2[0] == A(1)); + BOOST_TEST(s2[1] == A(2)); + BOOST_TEST(s2.get_deleter().state() == 1); + } + //Bounded array unique_ptr + reset_counters(); + { + A* p1 = new A[2]; + p1[0].set(1); + p1[1].set(2); + move_constr_deleter d1(1); + bml::unique_ptr > s1(p1, ::boost::move(d1)); + A* p2 = new A[2]; + p2[0].set(3); + p2[1].set(4); + move_constr_deleter d2(2); + bml::unique_ptr > s2(p2, ::boost::move(d2)); + BOOST_TEST(s1.get() == p1); + BOOST_TEST(s1[0] == A(1)); + BOOST_TEST(s1[1] == A(2)); + BOOST_TEST(s1.get_deleter().state() == 1); + BOOST_TEST(s2.get() == p2); + BOOST_TEST(s2[0] == A(3)); + BOOST_TEST(s2[1] == A(4)); + BOOST_TEST(s2.get_deleter().state() == 2); + swap(s1, s2); + BOOST_TEST(s1.get() == p2); + BOOST_TEST(s1[0] == A(3)); + BOOST_TEST(s1[1] == A(4)); + BOOST_TEST(s1.get_deleter().state() == 2); + BOOST_TEST(s2.get() == p1); + BOOST_TEST(s2[0] == A(1)); + BOOST_TEST(s2[1] == A(2)); + BOOST_TEST(s2.get_deleter().state() == 1); + } +} + +} //namespace unique_ptr_modifiers_swap{ + +//////////////////////////////// +// main +//////////////////////////////// +int main() +{ + //Modifiers + unique_ptr_modifiers_release::test(); + unique_ptr_modifiers_reset::test(); + unique_ptr_modifiers_reset_convert::test(); + unique_ptr_modifiers_swap::test(); + + //Test results + return boost::report_errors(); + +} + +#include "unique_ptr_test_utils_end.hpp" diff --git a/test/unique_ptr_movector.cpp b/test/unique_ptr_movector.cpp new file mode 100644 index 0000000..b8d7aa7 --- /dev/null +++ b/test/unique_ptr_movector.cpp @@ -0,0 +1,516 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Howard Hinnant 2009 +// (C) Copyright Ion Gaztanaga 2014-2014. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/move for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include + +////////////////////////////////////////////// +// +// The initial implementation of these tests +// was written by Howard Hinnant. +// +// These test were later refactored grouping +// and porting them to Boost.Move. +// +// Many thanks to Howard for releasing his C++03 +// unique_ptr implementation with such detailed +// test cases. +// +////////////////////////////////////////////// + +#include "unique_ptr_test_utils_beg.hpp" + +namespace bml = ::boost::movelib; + +//////////////////////////////// +// unique_ptr_ctor_move_defdel +//////////////////////////////// + +namespace unique_ptr_ctor_move_defdel{ + +// test converting move ctor. Should only require a MoveConstructible deleter, or if +// deleter is a reference, not even that. + +void test() +{ + //Single unique_ptr + reset_counters(); + { + bml::unique_ptr s(new A); + A* p = s.get(); + bml::unique_ptr s2(boost::move(s)); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 1); + } + BOOST_TEST(A::count == 0); + //Unbounded array unique_ptr + reset_counters(); + { + bml::unique_ptr s(new A[2]); + A* p = s.get(); + bml::unique_ptr s2(boost::move(s)); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 2); + } + BOOST_TEST(A::count == 0); + //Bounded array unique_ptr + reset_counters(); + { + bml::unique_ptr s(new A[2]); + A* p = s.get(); + bml::unique_ptr s2(boost::move(s)); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 2); + } + BOOST_TEST(A::count == 0); +} + +} //namespace unique_ptr_ctor_move_defdel{ + +//////////////////////////////// +// unique_ptr_ctor_move_movedel +//////////////////////////////// + +namespace unique_ptr_ctor_move_movedel{ + +// test converting move ctor. Should only require a MoveConstructible deleter, or if +// deleter is a reference, not even that. + +void test() +{ + //Single unique_ptr + reset_counters(); + { + bml::unique_ptr > s(new A); + A* p = s.get(); + bml::unique_ptr > s2 = boost::move(s); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 1); + BOOST_TEST(s2.get_deleter().state() == 5); + BOOST_TEST(s.get_deleter().state() == 0); + } + BOOST_TEST(A::count == 0); + //Unbounded array unique_ptr + reset_counters(); + { + bml::unique_ptr > s(new A[2]); + A* p = s.get(); + bml::unique_ptr > s2 = boost::move(s); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 2); + BOOST_TEST(s2.get_deleter().state() == 5); + BOOST_TEST(s.get_deleter().state() == 0); + } + BOOST_TEST(A::count == 0); + //Bounded array unique_ptr + reset_counters(); + { + bml::unique_ptr s(new A[2]); + A* p = s.get(); + bml::unique_ptr s2 = boost::move(s); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 2); + } + BOOST_TEST(A::count == 0); +} + +} //namespace unique_ptr_ctor_move_movedel{ + +//////////////////////////////// +// unique_ptr_ctor_move_dfctrdelref +//////////////////////////////// + +namespace unique_ptr_ctor_move_dfctrdelref{ + +// test converting move ctor. Should only require a MoveConstructible deleter, or if +// deleter is a reference, not even that. + +void test() +{ + //Single unique_ptr + reset_counters(); + { + def_constr_deleter d; + bml::unique_ptr&> s(new A, d); + A* p = s.get(); + bml::unique_ptr&> s2 = boost::move(s); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 1); + d.set_state(6); + BOOST_TEST(s2.get_deleter().state() == d.state()); + BOOST_TEST(s.get_deleter().state() == d.state()); + } + BOOST_TEST(A::count == 0); + //Unbounded array unique_ptr + reset_counters(); + { + def_constr_deleter d; + bml::unique_ptr&> s(new A[2], d); + A* p = s.get(); + bml::unique_ptr&> s2 = boost::move(s); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 2); + d.set_state(6); + BOOST_TEST(s2.get_deleter().state() == d.state()); + BOOST_TEST(s.get_deleter().state() == d.state()); + } + BOOST_TEST(A::count == 0); + //Bounded array unique_ptr + reset_counters(); + { + def_constr_deleter d; + bml::unique_ptr&> s(new A[2], d); + A* p = s.get(); + bml::unique_ptr&> s2(boost::move(s)); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 2); + d.set_state(6); + BOOST_TEST(s2.get_deleter().state() == d.state()); + BOOST_TEST(s.get_deleter().state() == d.state()); + } + BOOST_TEST(A::count == 0); +} + +} //namespace unique_ptr_ctor_move_dfctrdelref{ + +//////////////////////////////// +// unique_ptr_ctor_move_convert_defdel +//////////////////////////////// + +namespace unique_ptr_ctor_move_convert_defdel{ + +// test converting move ctor. Should only require a MoveConstructible deleter, or if +// deleter is a reference, not even that. + +void test() +{ + //Single unique_ptr + reset_counters(); + { + bml::unique_ptr s(new B); + A* p = s.get(); + bml::unique_ptr s2(boost::move(s)); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 1); + BOOST_TEST(B::count == 1); + } + BOOST_TEST(A::count == 0); + BOOST_TEST(B::count == 0); + //Unbounded array unique_ptr + reset_counters(); + { + bml::unique_ptr s(new A[2]); + A* p = s.get(); + bml::unique_ptr s2(boost::move(s)); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 2); + } + BOOST_TEST(A::count == 0); + + //Bounded array unique_ptr + reset_counters(); + { + bml::unique_ptr s(new A[2]); + A* p = s.get(); + bml::unique_ptr s2(boost::move(s)); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 2); + } + BOOST_TEST(A::count == 0); + { + bml::unique_ptr s(new A[2]); + A* p = s.get(); + bml::unique_ptr s2(boost::move(s)); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 2); + } + BOOST_TEST(A::count == 0); +} + +} //namespace unique_ptr_ctor_move_convert_defdel{ + +//////////////////////////////// +// unique_ptr_ctor_move_convert_movedel +//////////////////////////////// + +namespace unique_ptr_ctor_move_convert_movedel{ + +// test converting move ctor. Should only require a MoveConstructible deleter, or if +// deleter is a reference, not even that. + +void test() +{ + //Single unique_ptr + reset_counters(); + BOOST_STATIC_ASSERT((boost::move_detail::is_convertible::value)); + { + bml::unique_ptr > s(new B); + A* p = s.get(); + bml::unique_ptr > s2(boost::move(s)); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 1); + BOOST_TEST(B::count == 1); + BOOST_TEST(s2.get_deleter().state() == 5); + BOOST_TEST(s.get_deleter().state() == 0); + } + BOOST_TEST(A::count == 0); + BOOST_TEST(B::count == 0); + //Unbounded array unique_ptr + reset_counters(); + { + bml::unique_ptr > s(new const A[2]); + const A* p = s.get(); + bml::unique_ptr > s2(boost::move(s)); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 2); + BOOST_TEST(s2.get_deleter().state() == 5); + BOOST_TEST(s.get_deleter().state() == 0); + } + BOOST_TEST(A::count == 0); + BOOST_TEST(B::count == 0); + //Bounded array unique_ptr + reset_counters(); + { + bml::unique_ptr > s(new const A[2]); + const A* p = s.get(); + bml::unique_ptr > s2(boost::move(s)); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 2); + BOOST_TEST(s2.get_deleter().state() == 5); + BOOST_TEST(s.get_deleter().state() == 0); + } + BOOST_TEST(A::count == 0); + BOOST_TEST(B::count == 0); + { + bml::unique_ptr > s(new const A[2]); + const A* p = s.get(); + bml::unique_ptr > s2(boost::move(s)); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 2); + BOOST_TEST(s2.get_deleter().state() == 5); + BOOST_TEST(s.get_deleter().state() == 0); + } + BOOST_TEST(A::count == 0); + BOOST_TEST(B::count == 0); +} + +} //namespace unique_ptr_ctor_move_convert_movedel{ + +//////////////////////////////// +// unique_ptr_ctor_move_convert_dfctrdelref +//////////////////////////////// + +namespace unique_ptr_ctor_move_convert_dfctrdelref{ + +// test converting move ctor. Should only require a MoveConstructible deleter, or if +// deleter is a reference, not even that. + +void test() +{ + //Single unique_ptr + reset_counters(); + { + def_constr_deleter d; + bml::unique_ptr&> s(new B, d); + A* p = s.get(); + bml::unique_ptr&> s2(boost::move(s)); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 1); + BOOST_TEST(B::count == 1); + d.set_state(6); + BOOST_TEST(s2.get_deleter().state() == d.state()); + BOOST_TEST(s.get_deleter().state() == d.state()); + } + BOOST_TEST(A::count == 0); + BOOST_TEST(B::count == 0); + //Unbounded array unique_ptr + reset_counters(); + { + def_constr_deleter d; + bml::unique_ptr&> s(new A[2], d); + A* p = s.get(); + bml::unique_ptr&> s2(boost::move(s)); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 2); + d.set_state(6); + BOOST_TEST(s2.get_deleter().state() == d.state()); + BOOST_TEST(s.get_deleter().state() == d.state()); + } + BOOST_TEST(A::count == 0); + //Bounded array unique_ptr + reset_counters(); + { + def_constr_deleter d; + bml::unique_ptr&> s(new A[2], d); + A* p = s.get(); + bml::unique_ptr&> s2(boost::move(s)); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 2); + d.set_state(6); + BOOST_TEST(s2.get_deleter().state() == d.state()); + BOOST_TEST(s.get_deleter().state() == d.state()); + } + BOOST_TEST(A::count == 0); + { + def_constr_deleter d; + bml::unique_ptr&> s(new A[2], d); + A* p = s.get(); + bml::unique_ptr&> s2(boost::move(s)); + BOOST_TEST(s2.get() == p); + BOOST_TEST(s.get() == 0); + BOOST_TEST(A::count == 2); + d.set_state(6); + BOOST_TEST(s2.get_deleter().state() == d.state()); + BOOST_TEST(s.get_deleter().state() == d.state()); + } + BOOST_TEST(A::count == 0); +} + +} //namespace unique_ptr_ctor_move_convert_dfctrdelref{ + +//////////////////////////////// +// unique_ptr_ctor_move_sourcesink +//////////////////////////////// + +namespace unique_ptr_ctor_move_sourcesink{ + +// test move ctor. Should only require a MoveConstructible deleter, or if +// deleter is a reference, not even that. + +bml::unique_ptr source1() +{ return bml::unique_ptr(new A); } + +bml::unique_ptr source1_unbounded_array() +{ return bml::unique_ptr (new A[2]); } + +bml::unique_ptr source1_bounded_array() +{ return bml::unique_ptr (new A[2]); } + +void sink1(bml::unique_ptr) +{} + +void sink1_unbounded_array(bml::unique_ptr) +{} + +void sink1_bounded_array(bml::unique_ptr) +{} + +bml::unique_ptr > source2() +{ return bml::unique_ptr > (new A); } + +bml::unique_ptr > source2_unbounded_array() +{ return bml::unique_ptr >(new A[2]); } + +bml::unique_ptr > source2_bounded_array() +{ return bml::unique_ptr >(new A[2]); } + +void sink2(bml::unique_ptr >) +{} + +void sink2_unbounded_array(bml::unique_ptr >) +{} + +void sink2_bounded_array(bml::unique_ptr >) +{} + +bml::unique_ptr&> source3() +{ + static def_constr_deleter d; + return bml::unique_ptr&>(new A, d); +} + +bml::unique_ptr&> source3_unbounded_array() +{ + static def_constr_deleter d; + return bml::unique_ptr&>(new A[2], d); +} + +bml::unique_ptr&> source3_bounded_array() +{ + static def_constr_deleter d; + return bml::unique_ptr&>(new A[2], d); +} + +void sink3(bml::unique_ptr&> ) +{} + +void sink3_unbounded_array(bml::unique_ptr&> ) +{} + +void sink3_bounded_array(bml::unique_ptr&> ) +{} + +void test() +{ + //Single unique_ptr + reset_counters(); + sink1(source1()); + sink2(source2()); + sink3(source3()); + BOOST_TEST(A::count == 0); + //Unbounded array unique_ptr + reset_counters(); + sink1_unbounded_array(source1_unbounded_array()); + sink2_unbounded_array(source2_unbounded_array()); + sink3_unbounded_array(source3_unbounded_array()); + BOOST_TEST(A::count == 0); + //Bbounded array unique_ptr + reset_counters(); + sink1_bounded_array(source1_bounded_array()); + sink2_bounded_array(source2_bounded_array()); + sink3_bounded_array(source3_bounded_array()); + BOOST_TEST(A::count == 0); +} + +} //namespace unique_ptr_ctor_move_sourcesink{ + +//////////////////////////////// +// main +//////////////////////////////// +int main() +{ + //Move Constructor + unique_ptr_ctor_move_defdel::test(); + unique_ptr_ctor_move_movedel::test(); + unique_ptr_ctor_move_dfctrdelref::test(); + unique_ptr_ctor_move_convert_defdel::test(); + unique_ptr_ctor_move_convert_movedel::test(); + unique_ptr_ctor_move_convert_dfctrdelref::test(); + unique_ptr_ctor_move_sourcesink::test(); + + //Test results + return boost::report_errors(); +} + +#include "unique_ptr_test_utils_end.hpp" diff --git a/test/unique_ptr_nullptr.cpp b/test/unique_ptr_nullptr.cpp new file mode 100644 index 0000000..555fcc2 --- /dev/null +++ b/test/unique_ptr_nullptr.cpp @@ -0,0 +1,228 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Howard Hinnant 2009 +// (C) Copyright Ion Gaztanaga 2014-2014. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/move for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include + +////////////////////////////////////////////// +// +// The initial implementation of these tests +// was written by Howard Hinnant. +// +// These test were later refactored grouping +// and porting them to Boost.Move. +// +// Many thanks to Howard for releasing his C++03 +// unique_ptr implementation with such detailed +// test cases. +// +////////////////////////////////////////////// + +#include "unique_ptr_test_utils_beg.hpp" + +namespace bml = ::boost::movelib; + +//////////////////////////////// +// unique_ptr_zero +//////////////////////////////// +namespace unique_ptr_zero { + +// test initialization/assignment from zero + +void test() +{ + //Single unique_ptr + reset_counters(); + { + bml::unique_ptr s2(0); + BOOST_TEST(A::count == 0); + } + BOOST_TEST(A::count == 0); + { + bml::unique_ptr s2(new A); + BOOST_TEST(A::count == 1); + s2 = 0; + BOOST_TEST(A::count == 0); + BOOST_TEST(s2.get() == 0); + } + BOOST_TEST(A::count == 0); + + //Unbounded array unique_ptr + { + bml::unique_ptr s2(0); + BOOST_TEST(A::count == 0); + } + BOOST_TEST(A::count == 0); + { + bml::unique_ptr s2(new A[2]); + BOOST_TEST(A::count == 2); + s2 = 0; + BOOST_TEST(A::count == 0); + BOOST_TEST(s2.get() == 0); + } + BOOST_TEST(A::count == 0); + + //Bounded array unique_ptr + { + bml::unique_ptr s2(0); + BOOST_TEST(A::count == 0); + } + BOOST_TEST(A::count == 0); + { + bml::unique_ptr s2(new A[2]); + BOOST_TEST(A::count == 2); + s2 = 0; + BOOST_TEST(A::count == 0); + BOOST_TEST(s2.get() == 0); + } + BOOST_TEST(A::count == 0); +} + +} //namespace unique_ptr_zero { + + +//////////////////////////////// +// unique_ptr_nullptr +//////////////////////////////// + +namespace unique_ptr_nullptr{ + +void test() +{ + #if !defined(BOOST_NO_CXX11_NULLPTR) + //Single unique_ptr + reset_counters(); + { + bml::unique_ptr p(new A); + BOOST_TEST(A::count == 1); + A* i = p.get(); + (void)i; + p.reset(nullptr); + BOOST_TEST(A::count == 0); + BOOST_TEST(p.get() == 0); + } + BOOST_TEST(A::count == 0); + { + bml::unique_ptr p(new A); + BOOST_TEST(A::count == 1); + A* i = p.get(); + (void)i; + p = nullptr; + BOOST_TEST(A::count == 0); + BOOST_TEST(p.get() == 0); + } + BOOST_TEST(A::count == 0); + + { + bml::unique_ptr pi(nullptr); + BOOST_TEST(pi.get() == nullptr); + BOOST_TEST(pi.get() == 0); + } + BOOST_TEST(A::count == 0); + { + bml::unique_ptr pi(nullptr, bml::unique_ptr::deleter_type()); + BOOST_TEST(pi.get() == nullptr); + BOOST_TEST(pi.get() == 0); + } + BOOST_TEST(A::count == 0); + + //Unbounded array unique_ptr + reset_counters(); + { + bml::unique_ptr p(new A[2]); + BOOST_TEST(A::count == 2); + A* i = p.get(); + (void)i; + p.reset(nullptr); + BOOST_TEST(A::count == 0); + BOOST_TEST(p.get() == 0); + } + BOOST_TEST(A::count == 0); + { + bml::unique_ptr p(new A[2]); + BOOST_TEST(A::count == 2); + A* i = p.get(); + (void)i; + p = nullptr; + BOOST_TEST(A::count == 0); + BOOST_TEST(p.get() == 0); + } + BOOST_TEST(A::count == 0); + { + bml::unique_ptr pi(nullptr); + BOOST_TEST(pi.get() == nullptr); + BOOST_TEST(pi.get() == 0); + } + BOOST_TEST(A::count == 0); + { + bml::unique_ptr pi(nullptr, bml::unique_ptr::deleter_type()); + BOOST_TEST(pi.get() == nullptr); + BOOST_TEST(pi.get() == 0); + } + BOOST_TEST(A::count == 0); + + //Bounded array unique_ptr + reset_counters(); + { + bml::unique_ptr p(new A[2]); + BOOST_TEST(A::count == 2); + A* i = p.get(); + (void)i; + p.reset(nullptr); + BOOST_TEST(A::count == 0); + BOOST_TEST(p.get() == 0); + } + BOOST_TEST(A::count == 0); + { + bml::unique_ptr p(new A[2]); + BOOST_TEST(A::count == 2); + A* i = p.get(); + (void)i; + p = nullptr; + BOOST_TEST(A::count == 0); + BOOST_TEST(p.get() == 0); + } + BOOST_TEST(A::count == 0); + { + bml::unique_ptr pi(nullptr); + BOOST_TEST(pi.get() == nullptr); + BOOST_TEST(pi.get() == 0); + } + BOOST_TEST(A::count == 0); + { + bml::unique_ptr pi(nullptr, bml::unique_ptr::deleter_type()); + BOOST_TEST(pi.get() == nullptr); + BOOST_TEST(pi.get() == 0); + } + BOOST_TEST(A::count == 0); + #endif +} + +} //namespace unique_ptr_nullptr{ + +//////////////////////////////// +// main +//////////////////////////////// +int main() +{ + //nullptr + unique_ptr_zero::test(); + unique_ptr_nullptr::test(); + + //Test results + return boost::report_errors(); + +} + +#include "unique_ptr_test_utils_end.hpp" diff --git a/test/unique_ptr_observers.cpp b/test/unique_ptr_observers.cpp new file mode 100644 index 0000000..14376a0 --- /dev/null +++ b/test/unique_ptr_observers.cpp @@ -0,0 +1,287 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Howard Hinnant 2009 +// (C) Copyright Ion Gaztanaga 2014-2014. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/move for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include + +////////////////////////////////////////////// +// +// The initial implementation of these tests +// was written by Howard Hinnant. +// +// These test were later refactored grouping +// and porting them to Boost.Move. +// +// Many thanks to Howard for releasing his C++03 +// unique_ptr implementation with such detailed +// test cases. +// +////////////////////////////////////////////// + +#include "unique_ptr_test_utils_beg.hpp" + +namespace bml = ::boost::movelib; + +//////////////////////////////// +// unique_ptr_observers_dereference +//////////////////////////////// + +namespace unique_ptr_observers_dereference{ + +void test() +{ + //Single unique_ptr + { + bml::unique_ptr p(new int(3)); + BOOST_TEST(*p == 3); + } + //Unbounded array unique_ptr + { + int *pi = new int[2]; + pi[0] = 3; + pi[1] = 4; + bml::unique_ptr p(pi); + BOOST_TEST(p[0] == 3); + BOOST_TEST(p[1] == 4); + } + //Bounded array unique_ptr + { + int *pi = new int[2]; + pi[0] = 3; + pi[1] = 4; + bml::unique_ptr p(pi); + BOOST_TEST(p[0] == 3); + BOOST_TEST(p[1] == 4); + } +} + +} //namespace unique_ptr_observers_dereference{ + +//////////////////////////////// +// unique_ptr_observers_dereference +//////////////////////////////// + +namespace unique_ptr_observers_explicit_bool{ + +void test() +{ + //Single unique_ptr + { + bml::unique_ptr p(new int(3)); + if (p) + ; + else + BOOST_TEST(false); + if (!p) + BOOST_TEST(false); + } + { + bml::unique_ptr p; + if (!p) + ; + else + BOOST_TEST(false); + if (p) + BOOST_TEST(false); + } + //Unbounded array unique_ptr + { + bml::unique_ptr p(new int[2]); + if (p) + ; + else + BOOST_TEST(false); + if (!p) + BOOST_TEST(false); + } + { + bml::unique_ptr p; + if (!p) + ; + else + BOOST_TEST(false); + if (p) + BOOST_TEST(false); + } + //Bounded array unique_ptr + { + bml::unique_ptr p(new int[2]); + if (p) + ; + else + BOOST_TEST(false); + if (!p) + BOOST_TEST(false); + } + { + bml::unique_ptr p; + if (!p) + ; + else + BOOST_TEST(false); + if (p) + BOOST_TEST(false); + } +} + +} //namespace unique_ptr_observers_explicit_bool{ + +//////////////////////////////// +// unique_ptr_observers_get +//////////////////////////////// + +namespace unique_ptr_observers_get{ + +void test() +{ + //Single unique_ptr + { + int* p = new int; + bml::unique_ptr s(p); + BOOST_TEST(s.get() == p); + } + //Unbounded array unique_ptr + { + int* p = new int[2]; + bml::unique_ptr s(p); + BOOST_TEST(s.get() == p); + } + { + int* p = new int[2]; + bml::unique_ptr s(p); + BOOST_TEST(s.get() == p); + } + //Bounded array unique_ptr + { + int *pi = new int[2]; + pi[0] = 3; + pi[1] = 4; + bml::unique_ptr p(pi); + BOOST_TEST(p[0] == 3); + BOOST_TEST(p[1] == 4); + } +} + +} //namespace unique_ptr_observers_get{ + +//////////////////////////////// +// unique_ptr_observers_get_deleter +//////////////////////////////// + +namespace unique_ptr_observers_get_deleter{ + +struct Deleter +{ + void operator()(void*) {} + + int test() {return 5;} + int test() const {return 6;} +}; + +void test() +{ + //Single unique_ptr + { + bml::unique_ptr p; + BOOST_TEST(p.get_deleter().test() == 5); + } + { + const bml::unique_ptr p; + BOOST_TEST(p.get_deleter().test() == 6); + } + //Unbounded array unique_ptr + { + bml::unique_ptr p; + BOOST_TEST(p.get_deleter().test() == 5); + } + { + const bml::unique_ptr p; + BOOST_TEST(p.get_deleter().test() == 6); + } + //Bounded array unique_ptr + { + bml::unique_ptr p; + BOOST_TEST(p.get_deleter().test() == 5); + } + { + const bml::unique_ptr p; + BOOST_TEST(p.get_deleter().test() == 6); + } +} + +} //namespace unique_ptr_observers_get_deleter{ + +//////////////////////////////// +// unique_ptr_observers_op_arrow +//////////////////////////////// + +namespace unique_ptr_observers_op_arrow{ + +void test() +{ + //Single unique_ptr + { + bml::unique_ptr p(new A); + BOOST_TEST(p->state_ == 999); + } +} + +} //namespace unique_ptr_observers_op_arrow{ + + +namespace unique_ptr_observers_op_index{ + +void test() +{ + //Unbounded array unique_ptr + { + A *pa = new A[2]; + //pa[0] is left default constructed + pa[1].set(888); + bml::unique_ptr p(pa); + BOOST_TEST(p[0].state_ == 999); + BOOST_TEST(p[1].state_ == 888); + } + //Bounded array unique_ptr + { + A *pa = new A[2]; + //pa[0] is left default constructed + pa[1].set(888); + bml::unique_ptr p(pa); + BOOST_TEST(p[0].state_ == 999); + BOOST_TEST(p[1].state_ == 888); + } +} + +} //namespace unique_ptr_observers_op_index{ + +//////////////////////////////// +// main +//////////////////////////////// +int main() +{ + //Observers + unique_ptr_observers_dereference::test(); + unique_ptr_observers_explicit_bool::test(); + unique_ptr_observers_get::test(); + unique_ptr_observers_get_deleter::test(); + unique_ptr_observers_op_arrow::test(); + unique_ptr_observers_op_index::test(); + + //Test results + return boost::report_errors(); + +} + +#include "unique_ptr_test_utils_end.hpp" diff --git a/test/unique_ptr_test_utils_beg.hpp b/test/unique_ptr_test_utils_beg.hpp new file mode 100644 index 0000000..51995f5 --- /dev/null +++ b/test/unique_ptr_test_utils_beg.hpp @@ -0,0 +1,209 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Howard Hinnant 2009 +// (C) Copyright Ion Gaztanaga 2014-2014. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/move for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_MOVE_UNIQUE_PTR_TEST_UTILS_BEG_HPP +#define BOOST_MOVE_UNIQUE_PTR_TEST_UTILS_BEG_HPP +#include +#include +#include + +////////////////////////////////////////////// +// +// The initial implementation of these tests +// was written by Howard Hinnant. +// +// These test were later refactored grouping +// and porting them to Boost.Move. +// +// Many thanks to Howard for releasing his C++03 +// unique_ptr implementation with such detailed +// test cases. +// +////////////////////////////////////////////// + +//A deleter that can only default constructed +template +class def_constr_deleter +{ + int state_; + def_constr_deleter(const def_constr_deleter&); + def_constr_deleter& operator=(const def_constr_deleter&); + + public: + typedef typename ::boost::move_detail::remove_extent::type element_type; + static const bool is_array = ::boost::move_detail::is_array::value; + + def_constr_deleter() : state_(5) {} + + explicit def_constr_deleter(int s) : state_(s) {} + + int state() const {return state_;} + + void set_state(int s) {state_ = s;} + + void operator()(element_type* p) const + { is_array ? delete []p : delete p; } + + void operator()(element_type* p) + { ++state_; is_array ? delete []p : delete p; } +}; + +//A deleter that can be copy constructed +template +class copy_constr_deleter +{ + int state_; + + public: + typedef typename ::boost::move_detail::remove_extent::type element_type; + static const bool is_array = ::boost::move_detail::is_array::value; + + copy_constr_deleter() : state_(5) {} + + template + copy_constr_deleter(const copy_constr_deleter& + , typename boost::move_detail::enable_def_del::type* =0) + { state_ = 5; } + + explicit copy_constr_deleter(int s) : state_(s) {} + + template + typename boost::move_detail::enable_def_del::type + operator=(const copy_constr_deleter &d) + { + state_ = d.state(); + return *this; + } + + int state() const {return state_;} + + void set_state(int s) {state_ = s;} + + void operator()(element_type* p) const + { is_array ? delete []p : delete p; } + + void operator()(element_type* p) + { ++state_; is_array ? delete []p : delete p; } +}; + +//A deleter that can be only move constructed +template +class move_constr_deleter +{ + int state_; + + BOOST_MOVABLE_BUT_NOT_COPYABLE(move_constr_deleter) + + public: + typedef typename ::boost::move_detail::remove_extent::type element_type; + static const bool is_array = ::boost::move_detail::is_array::value; + + move_constr_deleter() : state_(5) {} + + move_constr_deleter(BOOST_RV_REF(move_constr_deleter) r) + : state_(r.state_) + { r.state_ = 0; } + + explicit move_constr_deleter(int s) : state_(s) {} + + template + move_constr_deleter(BOOST_RV_REF(move_constr_deleter) d + , typename boost::move_detail::enable_def_del::type* =0) + : state_(d.state()) + { d.set_state(0); } + + move_constr_deleter& operator=(BOOST_RV_REF(move_constr_deleter) r) + { + state_ = r.state_; + r.state_ = 0; + return *this; + } + + template + typename boost::move_detail::enable_def_del::type + operator=(BOOST_RV_REF(move_constr_deleter) d) + { + state_ = d.state(); + d.set_state(0); + return *this; + } + + int state() const {return state_;} + + void set_state(int s) {state_ = s;} + + void operator()(element_type* p) const + { is_array ? delete []p : delete p; } + + void operator()(element_type* p) + { ++state_; is_array ? delete []p : delete p; } + + friend bool operator==(const move_constr_deleter& x, const move_constr_deleter& y) + {return x.state_ == y.state_;} +}; + +//A base class containing state with a static instance counter +struct A +{ + int state_; + static int count; + + A() : state_(999) {++count;} + explicit A(int i) : state_(i) {++count;} + A(const A& a) : state_(a.state_) {++count;} + A& operator=(const A& a) { state_ = a.state_; return *this; } + void set(int i) {state_ = i;} + virtual ~A() {--count;} + friend bool operator==(const A& x, const A& y) { return x.state_ == y.state_; } +}; + +int A::count = 0; + +//A class derived from A with a static instance counter +struct B + : public A +{ + static int count; + B() {++count;} + B(const B&) {++count;} + virtual ~B() {--count;} +}; + +int B::count = 0; + +void reset_counters(); + +BOOST_STATIC_ASSERT((::boost::move_detail::is_convertible::value)); + +//Incomplete Type function declarations +struct I; +void check(int i); +I* get(); +I* get_array(int i); + +#include + +template > +struct J +{ + typedef boost::movelib::unique_ptr unique_ptr_type; + typedef typename unique_ptr_type::element_type element_type; + boost::movelib::unique_ptr a_; + J() {} + explicit J(element_type*a) : a_(a) {} + ~J(); + + element_type* get() const {return a_.get();} + D& get_deleter() {return a_.get_deleter();} +}; + +#endif //BOOST_MOVE_UNIQUE_PTR_TEST_UTILS_BEG_HPP diff --git a/test/unique_ptr_test_utils_end.hpp b/test/unique_ptr_test_utils_end.hpp new file mode 100644 index 0000000..ca0fb92 --- /dev/null +++ b/test/unique_ptr_test_utils_end.hpp @@ -0,0 +1,46 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Howard Hinnant 2009 +// (C) Copyright Ion Gaztanaga 2014-2014. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/move for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_MOVE_UNIQUE_PTR_TEST_UTILS_END_HPP +#define BOOST_MOVE_UNIQUE_PTR_TEST_UTILS_END_HPP + +#ifndef BOOST_MOVE_UNIQUE_PTR_TEST_UTILS_BEG_HPP +#error "unique_ptr_test_utils_beg.hpp MUST be included before this header" +#endif + +//Define the incomplete I type and out of line functions + +struct I +{ + static int count; + I() {++count;} + I(const A&) {++count;} + ~I() {--count;} +}; + +int I::count = 0; + +I* get() {return new I;} +I* get_array(int i) {return new I[i];} + +void check(int i) +{ + BOOST_TEST(I::count == i); +} + +template +J::~J() {} + +void reset_counters() +{ A::count = 0; B::count = 0; I::count = 0; } + +#endif //BOOST_MOVE_UNIQUE_PTR_TEST_UTILS_END_HPP diff --git a/test/unique_ptr_types.cpp b/test/unique_ptr_types.cpp new file mode 100644 index 0000000..6d7d4a8 --- /dev/null +++ b/test/unique_ptr_types.cpp @@ -0,0 +1,164 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Howard Hinnant 2009 +// (C) Copyright Ion Gaztanaga 2014-2014. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/move for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include + +////////////////////////////////////////////// +// +// The initial implementation of these tests +// was written by Howard Hinnant. +// +// These test were later refactored grouping +// and porting them to Boost.Move. +// +// Many thanks to Howard for releasing his C++03 +// unique_ptr implementation with such detailed +// test cases. +// +////////////////////////////////////////////// + +#include "unique_ptr_test_utils_beg.hpp" + +namespace bml = ::boost::movelib; + +//////////////////////////////// +// unique_ptr_pointer_type +//////////////////////////////// +namespace unique_ptr_pointer_type { + +struct Deleter +{ + struct pointer {}; +}; + +// Test unique_ptr::pointer type +void test() +{ + //Single unique_ptr + { + typedef bml::unique_ptr P; + BOOST_STATIC_ASSERT((boost::move_detail::is_same::value)); + } + { + typedef bml::unique_ptr P; + BOOST_STATIC_ASSERT((boost::move_detail::is_same::value)); + } + //Unbounded array unique_ptr + { + typedef bml::unique_ptr P; + BOOST_STATIC_ASSERT((boost::move_detail::is_same::value)); + } + { + typedef bml::unique_ptr P; + BOOST_STATIC_ASSERT((boost::move_detail::is_same::value)); + } + //Bounded array unique_ptr + { + typedef bml::unique_ptr P; + BOOST_STATIC_ASSERT((boost::move_detail::is_same::value)); + } + { + typedef bml::unique_ptr P; + BOOST_STATIC_ASSERT((boost::move_detail::is_same::value)); + } +} + +} //namespace unique_ptr_pointer_type { + +//////////////////////////////// +// unique_ptr_deleter_type +//////////////////////////////// +namespace unique_ptr_deleter_type { + +struct Deleter +{}; + +// Test unique_ptr::deleter type +void test() +{ + //Single unique_ptr + { + typedef bml::unique_ptr P; + BOOST_STATIC_ASSERT((boost::move_detail::is_same >::value)); + } + { + typedef bml::unique_ptr P; + BOOST_STATIC_ASSERT((boost::move_detail::is_same::value)); + } + //Unbounded array unique_ptr + { + typedef bml::unique_ptr P; + BOOST_STATIC_ASSERT((boost::move_detail::is_same >::value)); + } + { + typedef bml::unique_ptr P; + BOOST_STATIC_ASSERT((boost::move_detail::is_same::value)); + } + //Bounded array unique_ptr + { + typedef bml::unique_ptr P; + BOOST_STATIC_ASSERT((boost::move_detail::is_same >::value)); + } + { + typedef bml::unique_ptr P; + BOOST_STATIC_ASSERT((boost::move_detail::is_same::value)); + } +} + +} //namespace unique_ptr_deleter_type { + +//////////////////////////////// +// unique_ptr_element_type +//////////////////////////////// +namespace unique_ptr_element_type { + +// Test unique_ptr::deleter type +void test() +{ + //Single unique_ptr + { + typedef bml::unique_ptr P; + BOOST_STATIC_ASSERT((boost::move_detail::is_same::value)); + } + //Unbounded array unique_ptr + { + typedef bml::unique_ptr P; + BOOST_STATIC_ASSERT((boost::move_detail::is_same::value)); + } + //Bounded array unique_ptr + { + typedef bml::unique_ptr P; + BOOST_STATIC_ASSERT((boost::move_detail::is_same::value)); + } +} + +} //namespace unique_ptr_element_type { + +//////////////////////////////// +// main +//////////////////////////////// +int main() +{ + //General + unique_ptr_pointer_type::test(); + unique_ptr_deleter_type::test(); + unique_ptr_element_type::test(); + + //Test results + return boost::report_errors(); + +} + +#include "unique_ptr_test_utils_end.hpp" From 90be9ebe225acf68c860f20c0f4367b1ac1913ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Tue, 2 Sep 2014 16:28:17 +0200 Subject: [PATCH 07/10] Extracted default_delete into its own header. Extracted meta utilities used only by unique_ptr and friends to its own "unique_ptr_meta_utils.hpp" header. --- include/boost/move/default_delete.hpp | 173 ++++++ .../move/detail/unique_ptr_meta_utils.hpp | 523 ++++++++++++++++++ include/boost/move/unique_ptr.hpp | 335 ++++------- proj/vc7ide/Move.sln | 3 +- test/unique_ptr_default_deleter.cpp | 2 +- test/unique_ptr_movector.cpp | 3 +- test/unique_ptr_test_utils_beg.hpp | 8 +- test/unique_ptr_types.cpp | 31 +- 8 files changed, 815 insertions(+), 263 deletions(-) create mode 100644 include/boost/move/default_delete.hpp create mode 100644 include/boost/move/detail/unique_ptr_meta_utils.hpp diff --git a/include/boost/move/default_delete.hpp b/include/boost/move/default_delete.hpp new file mode 100644 index 0000000..dab8a83 --- /dev/null +++ b/include/boost/move/default_delete.hpp @@ -0,0 +1,173 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2014-2014. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/move for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_MOVE_DEFAULT_DELETE_HPP_INCLUDED +#define BOOST_MOVE_DEFAULT_DELETE_HPP_INCLUDED + +#include +#include +#include +#include +#include + +#include //For std::size_t + +//!\file +//! Describes the default deleter (destruction policy) of unique_ptr: default_delete. + +namespace boost{ +namespace move_upd { + +namespace bmupmu = ::boost::move_upmu; + +//////////////////////////////////////// +//// enable_def_del +//////////////////////////////////////// + +//compatible with a pointer type T*: +//When either Y* is convertible to T* +//Y is U[N] and T is U cv [] +template +struct def_del_compatible_cond + : bmupmu::is_convertible +{}; + +template +struct def_del_compatible_cond + : def_del_compatible_cond +{}; + +template +struct enable_def_del + : bmupmu::enable_if_c::value, Type> +{}; + +//////////////////////////////////////// +//// enable_defdel_call +//////////////////////////////////////// + +//When 2nd is T[N], 1st(*)[N] shall be convertible to T(*)[N]; +//When 2nd is T[], 1st(*)[] shall be convertible to T(*)[]; +//Otherwise, 1st* shall be convertible to 2nd*. + +template +struct enable_defdel_call + : public enable_def_del +{}; + +template +struct enable_defdel_call + : public enable_def_del +{}; + +template +struct enable_defdel_call + : public enable_def_del +{}; + +//////////////////////////////////////// +//// Some bool literal zero conversion utilities +//////////////////////////////////////// + +struct bool_conversion {int for_bool; int for_arg(); }; +typedef int bool_conversion::* explicit_bool_arg; + +#if !defined(BOOST_NO_CXX11_NULLPTR) +typedef std::nullptr_t nullptr_type; +#else +typedef int (bool_conversion::*nullptr_type)(); +#endif + +} //namespace move_upd { + +namespace movelib { + +namespace bmupd = boost::move_upd; +namespace bmupmu = boost::move_detail; + +//!The class template default_delete serves as the default deleter +//!(destruction policy) for the class template unique_ptr. +//! +//! \tparam T The type to be deleted. It may be an incomplete type +template +struct default_delete +{ + //! Default constructor. + //! + BOOST_CONSTEXPR default_delete() + //Avoid "defaulted on its first declaration must not have an exception-specification" error for GCC 4.6 + #if !defined(BOOST_GCC) || (BOOST_GCC < 40600 && BOOST_GCC >= 40700) || defined(BOOST_MOVE_DOXYGEN_INVOKED) + BOOST_NOEXCEPT + #endif + #if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || defined(BOOST_MOVE_DOXYGEN_INVOKED) + = default; + #else + {}; + #endif + + #if defined(BOOST_MOVE_DOXYGEN_INVOKED) + default_delete(const default_delete&) BOOST_NOEXCEPT = default; + default_delete &operator=(const default_delete&) BOOST_NOEXCEPT = default; + #else + typedef typename bmupmu::remove_extent::type element_type; + #endif + + //! Effects: Constructs a default_delete object from another default_delete object. + //! + //! Remarks: This constructor shall not participate in overload resolution unless: + //! - If T is not an array type and U* is implicitly convertible to T*. + //! - If T is an array type and U* is a more CV qualified pointer to remove_extent::type. + template + default_delete(const default_delete& + BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_def_del::type* =0) + ) BOOST_NOEXCEPT + {} + + //! Effects: Constructs a default_delete object from another default_delete object. + //! + //! Remarks: This constructor shall not participate in overload resolution unless: + //! - If T is not an array type and U* is implicitly convertible to T*. + //! - If T is an array type and U* is a more CV qualified pointer to remove_extent::type. + template + BOOST_MOVE_DOC1ST(default_delete&, + typename bmupd::enable_def_del::type) + operator=(const default_delete&) BOOST_NOEXCEPT + { return *this; } + + //! Effects: if T is not an array type, calls delete on static_cast(ptr), + //! otherwise calls delete[] on static_cast::type*>(ptr). + //! + //! Remarks: If U is an incomplete type, the program is ill-formed. + //! This operator shall not participate in overload resolution unless: + //! - T is not an array type and U* is convertible to T*, OR + //! - T is an array type, and remove_cv::type is the same type as + //! remove_cv::type>::type and U* is convertible to remove_extent::type*. + template + BOOST_MOVE_DOC1ST(void, typename bmupd::enable_defdel_call::type) + operator()(U* ptr) const BOOST_NOEXCEPT + { + //U must be a complete type + BOOST_STATIC_ASSERT(sizeof(U) > 0); + element_type * const p = static_cast(ptr); + bmupmu::is_array::value ? delete [] p : delete p; + } + + //! Effects: Same as (*this)(static_cast(nullptr)). + //! + void operator()(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) const BOOST_NOEXCEPT + { BOOST_STATIC_ASSERT(sizeof(element_type) > 0); } +}; + +} //namespace movelib { +} //namespace boost{ + +#include + +#endif //#ifndef BOOST_MOVE_DEFAULT_DELETE_HPP_INCLUDED diff --git a/include/boost/move/detail/unique_ptr_meta_utils.hpp b/include/boost/move/detail/unique_ptr_meta_utils.hpp new file mode 100644 index 0000000..33e4d52 --- /dev/null +++ b/include/boost/move/detail/unique_ptr_meta_utils.hpp @@ -0,0 +1,523 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2012-2012. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/move for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +//! \file + +#ifndef BOOST_MOVE_UNIQUE_PTR_DETAIL_META_UTILS_HPP +#define BOOST_MOVE_UNIQUE_PTR_DETAIL_META_UTILS_HPP + +#include //for std::size_t + +//Small meta-typetraits to support move + +namespace boost { + +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES +//Forward declare boost::rv +template class rv; +#endif + +namespace move_upmu { + +////////////////////////////////////// +// nat +////////////////////////////////////// +struct nat{}; + +////////////////////////////////////// +// natify +////////////////////////////////////// +template struct natify{}; + +////////////////////////////////////// +// if_c +////////////////////////////////////// +template +struct if_c +{ + typedef T1 type; +}; + +template +struct if_c +{ + typedef T2 type; +}; + +////////////////////////////////////// +// if_ +////////////////////////////////////// +template +struct if_ : if_c<0 != T1::value, T2, T3> +{}; + +//enable_if_ +template +struct enable_if_c +{ + typedef T type; +}; + +////////////////////////////////////// +// enable_if_c +////////////////////////////////////// +template +struct enable_if_c {}; + +////////////////////////////////////// +// enable_if +////////////////////////////////////// +template +struct enable_if : public enable_if_c {}; + +////////////////////////////////////// +// remove_reference +////////////////////////////////////// +template +struct remove_reference +{ + typedef T type; +}; + +template +struct remove_reference +{ + typedef T type; +}; + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +template +struct remove_reference +{ + typedef T type; +}; + +#else + +template +struct remove_reference< rv > +{ + typedef T type; +}; + +template +struct remove_reference< rv &> +{ + typedef T type; +}; + +template +struct remove_reference< const rv &> +{ + typedef T type; +}; + + +#endif + +////////////////////////////////////// +// remove_const +////////////////////////////////////// +template< class T > +struct remove_const +{ + typedef T type; +}; + +template< class T > +struct remove_const +{ + typedef T type; +}; + +////////////////////////////////////// +// remove_volatile +////////////////////////////////////// +template< class T > +struct remove_volatile +{ + typedef T type; +}; + +template< class T > +struct remove_volatile +{ + typedef T type; +}; + +////////////////////////////////////// +// remove_cv +////////////////////////////////////// +template< class T > +struct remove_cv +{ + typedef typename remove_volatile + ::type>::type type; +}; + +////////////////////////////////////// +// remove_extent +////////////////////////////////////// +template +struct remove_extent +{ + typedef T type; +}; + +template +struct remove_extent +{ + typedef T type; +}; + +template +struct remove_extent +{ + typedef T type; +}; + +////////////////////////////////////// +// extent +////////////////////////////////////// + +template +struct extent +{ + static const std::size_t value = 0; +}; + +template +struct extent +{ + static const std::size_t value = 0; +}; + +template +struct extent +{ + static const std::size_t value = extent::value; +}; + +template +struct extent +{ + static const std::size_t value = N; +}; + +template +struct extent +{ + static const std::size_t value = extent::value; +}; + +////////////////////////////////////// +// add_lvalue_reference +////////////////////////////////////// +template +struct add_lvalue_reference +{ + typedef T& type; +}; + +template +struct add_lvalue_reference +{ + typedef T& type; +}; + +template<> +struct add_lvalue_reference +{ + typedef void type; +}; + +template<> +struct add_lvalue_reference +{ + typedef const void type; +}; + +template<> +struct add_lvalue_reference +{ + typedef volatile void type; +}; + +template<> +struct add_lvalue_reference +{ + typedef const volatile void type; +}; + +template +struct add_const_lvalue_reference +{ + typedef typename remove_reference::type t_unreferenced; + typedef const t_unreferenced t_unreferenced_const; + typedef typename add_lvalue_reference + ::type type; +}; + +////////////////////////////////////// +// is_same +////////////////////////////////////// +template +struct is_same +{ + static const bool value = false; +}; + +template +struct is_same +{ + static const bool value = true; +}; + +////////////////////////////////////// +// is_pointer +////////////////////////////////////// +template< class T > +struct is_pointer +{ + static const bool value = false; +}; + +template< class T > +struct is_pointer +{ + static const bool value = true; +}; + +////////////////////////////////////// +// is_reference +////////////////////////////////////// +template< class T > +struct is_reference +{ + static const bool value = false; +}; + +template< class T > +struct is_reference +{ + static const bool value = true; +}; + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +template< class T > +struct is_reference +{ + static const bool value = true; +}; + +#endif + +////////////////////////////////////// +// is_lvalue_reference +////////////////////////////////////// +template +struct is_lvalue_reference +{ + static const bool value = false; +}; + +template +struct is_lvalue_reference +{ + static const bool value = true; +}; + +////////////////////////////////////// +// is_array +////////////////////////////////////// +template +struct is_array +{ + static const bool value = false; +}; + +template +struct is_array +{ + static const bool value = true; +}; + +template +struct is_array +{ + static const bool value = true; +}; + +////////////////////////////////////// +// has_pointer_type +////////////////////////////////////// +template +struct has_pointer_type +{ + struct two { char c[2]; }; + template static two test(...); + template static char test(typename U::pointer* = 0); + static const bool value = sizeof(test(0)) == 1; +}; + +////////////////////////////////////// +// pointer_type +////////////////////////////////////// +template ::value> +struct pointer_type_imp +{ + typedef typename D::pointer type; +}; + +template +struct pointer_type_imp +{ + typedef typename remove_extent::type* type; +}; + +template +struct pointer_type +{ + typedef typename pointer_type_imp + ::type, typename remove_reference::type>::type type; +}; + +////////////////////////////////////// +// is_convertible +////////////////////////////////////// +#if defined(_MSC_VER) && (_MSC_VER >= 1400) + +//use intrinsic since in MSVC +//overaligned types can't go through ellipsis +template +struct is_convertible +{ + static const bool value = __is_convertible_to(T, U); +}; + +#else + +template +class is_convertible +{ + typedef typename add_lvalue_reference::type t_reference; + typedef char true_t; + class false_t { char dummy[2]; }; + static false_t dispatch(...); + static true_t dispatch(U); + static t_reference trigger(); + public: + static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t); +}; + +#endif + +////////////////////////////////////// +// is_unary_function +////////////////////////////////////// +#if defined(BOOST_MSVC) || defined(__BORLANDC_) +#define BOOST_MOVE_TT_DECL __cdecl +#else +#define BOOST_MOVE_TT_DECL +#endif + +#if defined(_MSC_EXTENSIONS) && !defined(__BORLAND__) && !defined(_WIN64) && !defined(_M_ARM) && !defined(UNDER_CE) +#define BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS +#endif + +template +struct is_unary_function_impl +{ static const bool value = false; }; + +// avoid duplicate definitions of is_unary_function_impl +#ifndef BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS + +template +struct is_unary_function_impl +{ static const bool value = true; }; + +template +struct is_unary_function_impl +{ static const bool value = true; }; + +#else // BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS + +template +struct is_unary_function_impl +{ static const bool value = true; }; + +#ifndef _MANAGED + +template +struct is_unary_function_impl +{ static const bool value = true; }; + +#endif + +template +struct is_unary_function_impl +{ static const bool value = true; }; + +template +struct is_unary_function_impl +{ static const bool value = true; }; + +#endif + +// avoid duplicate definitions of is_unary_function_impl +#ifndef BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS + +template +struct is_unary_function_impl +{ static const bool value = true; }; + +template +struct is_unary_function_impl +{ static const bool value = true; }; + +#else // BOOST_MOVE_TT_TEST_MSC_FUNC_SIGS + +template +struct is_unary_function_impl +{ static const bool value = true; }; + +#ifndef _MANAGED + +template +struct is_unary_function_impl +{ static const bool value = true; }; + +#endif + +template +struct is_unary_function_impl +{ static const bool value = true; }; + +template +struct is_unary_function_impl +{ static const bool value = true; }; + +#endif + +template +struct is_unary_function_impl +{ static const bool value = false; }; + +template +struct is_unary_function +{ static const bool value = is_unary_function_impl::value; }; + +} //namespace move_upmu { +} //namespace boost { + +#endif //#ifndef BOOST_MOVE_UNIQUE_PTR_DETAIL_META_UTILS_HPP diff --git a/include/boost/move/unique_ptr.hpp b/include/boost/move/unique_ptr.hpp index 5544d55..a78ca66 100644 --- a/include/boost/move/unique_ptr.hpp +++ b/include/boost/move/unique_ptr.hpp @@ -13,8 +13,9 @@ #include #include +#include +#include #include -#include #include #include @@ -36,8 +37,7 @@ //! cv-less T and cv-less U are the same type and T is more CV qualified than U. namespace boost{ - -namespace move_detail { +namespace move_upd { //////////////////////////////////////////// // deleter types @@ -58,25 +58,25 @@ class is_noncopyable template struct deleter_types { - typedef typename add_lvalue_reference::type del_ref; - typedef typename add_const_lvalue_reference::type del_cref; + typedef typename bmupmu::add_lvalue_reference::type del_ref; + typedef typename bmupmu::add_const_lvalue_reference::type del_cref; #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - typedef typename if_c - < is_lvalue_reference::value, D, del_cref >::type deleter_arg_type1; - typedef typename remove_reference::type && deleter_arg_type2; + typedef typename bmupmu::if_c + < bmupmu::is_lvalue_reference::value, D, del_cref >::type deleter_arg_type1; + typedef typename bmupmu::remove_reference::type && deleter_arg_type2; #else - typedef typename if_c - < is_noncopyable::value, nat, del_cref>::type non_ref_deleter_arg1; - typedef typename if_c< is_lvalue_reference::value - , D, non_ref_deleter_arg1 >::type deleter_arg_type1; - typedef ::boost::rv & deleter_arg_type2; + typedef typename bmupmu::if_c + < is_noncopyable::value, bmupmu::nat, del_cref>::type non_ref_deleter_arg1; + typedef typename bmupmu::if_c< bmupmu::is_lvalue_reference::value + , D, non_ref_deleter_arg1 >::type deleter_arg_type1; + typedef ::boost::rv & deleter_arg_type2; #endif }; //////////////////////////////////////////// // unique_ptr_data //////////////////////////////////////////// -template ::value || is_reference::value > +template ::value || bmupmu::is_reference::value > struct unique_ptr_data { typedef typename deleter_types::deleter_arg_type1 deleter_arg_type1; @@ -155,11 +155,11 @@ struct unique_ptr_data template struct get_element_type { - struct DefaultWrap { typedef natify element_type; }; + struct DefaultWrap { typedef bmupmu::natify element_type; }; template static char test(int, typename X::element_type*); template static int test(...); static const bool value = (1 == sizeof(test(0, 0))); - typedef typename if_c::type::element_type type; + typedef typename bmupmu::if_c::type::element_type type; }; template @@ -170,18 +170,17 @@ struct get_element_type template struct get_cvelement -{ - typedef typename remove_cv::type>::type type; -}; + : bmupmu::remove_cv::type> +{}; template struct is_same_cvelement_and_convertible { - typedef typename remove_reference::type arg1; - typedef typename remove_reference::type arg2; + typedef typename bmupmu::remove_reference::type arg1; + typedef typename bmupmu::remove_reference::type arg2; static const bool same_cvless = - is_same::type,typename get_cvelement::type>::value; - static const bool value = same_cvless && is_convertible::value; + bmupmu::is_same::type,typename get_cvelement::type>::value; + static const bool value = same_cvless && bmupmu::is_convertible::value; }; template @@ -191,63 +190,17 @@ struct is_unique_ptr_convertible template struct is_unique_ptr_convertible - : is_convertible -{}; - -//////////////////////////////////////// -//// enable_def_del -//////////////////////////////////////// - -//compatible with a pointer type T*: -//When either Y* is convertible to T* -//Y is U[N] and T is U cv [] -template -struct def_del_compatible_cond -{ - static const bool value = is_convertible::value; -}; - -template -struct def_del_compatible_cond -{ - static const bool value = def_del_compatible_cond::value; -}; - -template -struct enable_def_del - : enable_if_c::value, Type> -{}; - -//////////////////////////////////////// -//// enable_defdel_call -//////////////////////////////////////// - -//When 2nd is T[N], 1st(*)[N] shall be convertible to T[N]*; -//When 2nd is T[], 1st(*)[] shall be convertible to T[]*; -//Otherwise, 1st* shall be convertible to 2nd*. - -template -struct enable_defdel_call - : public enable_def_del -{}; - -template -struct enable_defdel_call - : public enable_def_del -{}; - -template -struct enable_defdel_call - : public enable_def_del + : bmupmu::is_convertible {}; //////////////////////////////////////// //// enable_up_moveconv_assign //////////////////////////////////////// -template +template struct enable_up_ptr - : enable_if_c< is_unique_ptr_convertible < is_array::value, FromPointer, ThisPointer>::value, Type> + : bmupmu::enable_if_c< is_unique_ptr_convertible + < bmupmu::is_array::value, FromPointer, ThisPointer>::value, Type> {}; //////////////////////////////////////// @@ -257,53 +210,40 @@ struct enable_up_ptr template struct unique_moveconvert_assignable { - static const bool value = (extent::value == extent::value)&& is_unique_ptr_convertible - ::value, typename pointer_type::type, typename pointer_type::type>::value; + static const bool value = (bmupmu::extent::value == bmupmu::extent::value) && is_unique_ptr_convertible + < bmupmu::is_array::value + , typename bmupmu::pointer_type::type, typename bmupmu::pointer_type::type>::value; }; template struct unique_moveconvert_assignable -{ - static const bool value = unique_moveconvert_assignable::value; -}; -/* -template -struct unique_moveconvert_assignable -{ - static const bool value = unique_moveconvert_assignable::value; -}; + : unique_moveconvert_assignable +{}; -template -struct unique_moveconvert_assignable -{ - static const bool value = (M == N) && unique_moveconvert_assignable::value; -}; -*/ -template +template struct enable_up_moveconv_assign - : enable_if_c::value, Type> + : bmupmu::enable_if_c::value, Type> {}; //////////////////////////////////////// //// enable_up_moveconv_constr //////////////////////////////////////// -template::value> +template::value> struct unique_deleter_is_initializable -{ - static const bool value = is_same::value; -}; + : bmupmu::is_same +{}; template class is_rvalue_convertible { #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - typedef typename remove_reference::type&& t_from; + typedef typename bmupmu::remove_reference::type&& t_from; #else - typedef typename if_c - < has_move_emulation_enabled::value && !is_reference::value - , boost::rv& - , typename add_lvalue_reference::type + typedef typename bmupmu::if_c + < ::boost::has_move_emulation_enabled::value && !bmupmu::is_reference::value + , ::boost::rv& + , typename bmupmu::add_lvalue_reference::type >::type t_from; #endif @@ -339,103 +279,16 @@ struct unique_deleter_is_initializable #endif }; -template +template struct enable_up_moveconv_constr - : enable_if_c::value && - unique_deleter_is_initializable::value, Type> + : bmupmu::enable_if_c::value && + unique_deleter_is_initializable::value, Type> {}; -//////////////////////////////////////// -//// Some bool literal zero conversion utilities -//////////////////////////////////////// - -struct bool_conversion {int for_bool; int for_arg(); }; -typedef int bool_conversion::* explicit_bool_arg; - -#if !defined(BOOST_NO_CXX11_NULLPTR) -typedef std::nullptr_t nullptr_type; -#else -typedef int (bool_conversion::*nullptr_type)(); -#endif - -} //namespace move_detail { +} //namespace move_upd { namespace movelib { -namespace bmd = boost::move_detail; - -//!The class template default_delete serves as the default deleter -//!(destruction policy) for the class template unique_ptr. -template -struct default_delete -{ - //! Default constructor. - //! - BOOST_CONSTEXPR default_delete() - //Avoid "defaulted on its first declaration must not have an exception-specification" error for GCC 4.6 - #if !defined(BOOST_GCC) || (BOOST_GCC < 40600 && BOOST_GCC >= 40700) || defined(BOOST_MOVE_DOXYGEN_INVOKED) - BOOST_NOEXCEPT - #endif - #if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || defined(BOOST_MOVE_DOXYGEN_INVOKED) - = default; - #else - {}; - #endif - - #if defined(BOOST_MOVE_DOXYGEN_INVOKED) - default_delete(const default_delete&) BOOST_NOEXCEPT = default; - default_delete &operator=(const default_delete&) BOOST_NOEXCEPT = default; - #else - typedef typename bmd::remove_extent::type element_type; - #endif - - //! Effects: Constructs a default_delete object from another default_delete object. - //! - //! Remarks: This constructor shall not participate in overload resolution unless: - //! - If T is not an array type and U* is implicitly convertible to T*. - //! - If T is an array type and U* is a more CV qualified pointer to remove_extent::type. - template - default_delete(const default_delete& - BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmd::enable_def_del::type* =0) - ) BOOST_NOEXCEPT - {} - - //! Effects: Constructs a default_delete object from another default_delete object. - //! - //! Remarks: This constructor shall not participate in overload resolution unless: - //! - If T is not an array type and U* is implicitly convertible to T*. - //! - If T is an array type and U* is a more CV qualified pointer to remove_extent::type. - template - BOOST_MOVE_DOC1ST(default_delete&, - typename bmd::enable_def_del::type) - operator=(const default_delete&) BOOST_NOEXCEPT - { return *this; } - - //! Effects: if T is not an array type, calls delete on static_cast(ptr), - //! otherwise calls delete[] on static_cast::type*>(ptr). - //! - //! Remarks: If U is an incomplete type, the program is ill-formed. - //! This operator shall not participate in overload resolution unless: - //! - T is not an array type and U* is convertible to T*, OR - //! - T is an array type, and remove_cv::type is the same type as - //! remove_cv::type>::type and U* is convertible to remove_extent::type*. - template - BOOST_MOVE_DOC1ST(void, typename bmd::enable_defdel_call::type) - operator()(U* ptr) const BOOST_NOEXCEPT - { - //U must be a complete type - BOOST_STATIC_ASSERT(sizeof(U) > 0); - element_type * const p = static_cast(ptr); - bmd::is_array::value ? delete [] p : delete p; - } - - //! Effects: Same as (*this)(static_cast(nullptr)). - //! - void operator()(BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) const BOOST_NOEXCEPT - { BOOST_STATIC_ASSERT(sizeof(element_type) > 0); } -}; - - //! A unique pointer is an object that owns another object and //! manages that other object through a pointer. //! @@ -491,11 +344,11 @@ class unique_ptr #else BOOST_MOVABLE_BUT_NOT_COPYABLE(unique_ptr) - typedef move_detail::pointer_type pointer_type_obtainer; - typedef bmd::unique_ptr_data + typedef bmupmu::pointer_type pointer_type_obtainer; + typedef bmupd::unique_ptr_data data_type; - typedef typename bmd::deleter_types::deleter_arg_type1 deleter_arg_type1; - typedef typename bmd::deleter_types::deleter_arg_type2 deleter_arg_type2; + typedef typename bmupd::deleter_types::deleter_arg_type1 deleter_arg_type1; + typedef typename bmupd::deleter_types::deleter_arg_type2 deleter_arg_type2; data_type m_data; #endif @@ -506,7 +359,7 @@ class unique_ptr typedef typename BOOST_MOVE_SEEDOC(pointer_type_obtainer::type) pointer; //! If T is an array type, then element_type is equal to T. Otherwise, if T is a type //! in the form U[], element_type is equal to U. - typedef typename BOOST_MOVE_SEEDOC(bmd::remove_extent::type) element_type; + typedef typename BOOST_MOVE_SEEDOC(bmupmu::remove_extent::type) element_type; typedef D deleter_type; //! Requires: D shall satisfy the requirements of DefaultConstructible, and @@ -524,19 +377,19 @@ class unique_ptr { //If this constructor is instantiated with a pointer type or reference type //for the template argument D, the program is ill-formed. - BOOST_STATIC_ASSERT(!bmd::is_pointer::value); - BOOST_STATIC_ASSERT(!bmd::is_reference::value); + BOOST_STATIC_ASSERT(!bmupmu::is_pointer::value); + BOOST_STATIC_ASSERT(!bmupmu::is_reference::value); } //! Effects: Same as unique_ptr() (default constructor). //! - BOOST_CONSTEXPR unique_ptr(BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) BOOST_NOEXCEPT + BOOST_CONSTEXPR unique_ptr(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT : m_data() { //If this constructor is instantiated with a pointer type or reference type //for the template argument D, the program is ill-formed. - BOOST_STATIC_ASSERT(!bmd::is_pointer::value); - BOOST_STATIC_ASSERT(!bmd::is_reference::value); + BOOST_STATIC_ASSERT(!bmupmu::is_pointer::value); + BOOST_STATIC_ASSERT(!bmupmu::is_reference::value); } //! Requires: D shall satisfy the requirements of DefaultConstructible, and @@ -554,14 +407,14 @@ class unique_ptr //! - If T is an array type and Pointer is a more CV qualified pointer to element_type. template explicit unique_ptr(Pointer p - BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmd::enable_up_ptr::type* =0) + BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_ptr::type* =0) ) BOOST_NOEXCEPT : m_data(p) { //If this constructor is instantiated with a pointer type or reference type //for the template argument D, the program is ill-formed. - BOOST_STATIC_ASSERT(!bmd::is_pointer::value); - BOOST_STATIC_ASSERT(!bmd::is_reference::value); + BOOST_STATIC_ASSERT(!bmupmu::is_pointer::value); + BOOST_STATIC_ASSERT(!bmupmu::is_reference::value); } //!The signature of this constructor depends upon whether D is a reference type. @@ -588,14 +441,14 @@ class unique_ptr //! - If T is an array type and Pointer is a more CV qualified pointer to element_type. template unique_ptr(Pointer p, BOOST_MOVE_SEEDOC(deleter_arg_type1) d1 - BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmd::enable_up_ptr::type* =0) + BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_ptr::type* =0) ) BOOST_NOEXCEPT : m_data(p, d1) {} //! Effects: Same effects as template unique_ptr(Pointer p, deleter_arg_type1 d1) //! and additionally get() == nullptr - unique_ptr(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), BOOST_MOVE_SEEDOC(deleter_arg_type1) d1) BOOST_NOEXCEPT + unique_ptr(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), BOOST_MOVE_SEEDOC(deleter_arg_type1) d1) BOOST_NOEXCEPT : m_data(pointer(), d1) {} @@ -621,14 +474,14 @@ class unique_ptr //! - If T is an array type and Pointer is a more CV qualified pointer to element_type. template unique_ptr(Pointer p, BOOST_MOVE_SEEDOC(deleter_arg_type2) d2 - BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmd::enable_up_ptr::type* =0) + BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_ptr::type* =0) ) BOOST_NOEXCEPT : m_data(p, ::boost::move(d2)) {} //! Effects: Same effects as template unique_ptr(Pointer p, deleter_arg_type2 d2) //! and additionally get() == nullptr - unique_ptr(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), BOOST_MOVE_SEEDOC(deleter_arg_type2) d2) BOOST_NOEXCEPT + unique_ptr(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), BOOST_MOVE_SEEDOC(deleter_arg_type2) d2) BOOST_NOEXCEPT : m_data(pointer(), ::boost::move(d2)) {} @@ -663,7 +516,7 @@ class unique_ptr //! returns a reference to the stored deleter that was constructed from u.get_deleter(). template unique_ptr( BOOST_RV_REF_BEG unique_ptr BOOST_RV_REF_END u - BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmd::enable_up_moveconv_constr::type* =0) + BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_moveconv_constr::type* =0) ) BOOST_NOEXCEPT : m_data(u.release(), ::boost::move_if_not_lvalue_reference(u.get_deleter())) {} @@ -706,7 +559,7 @@ class unique_ptr //! //! Returns: *this. template - BOOST_MOVE_DOC1ST(unique_ptr&, typename bmd::enable_up_moveconv_assign + BOOST_MOVE_DOC1ST(unique_ptr&, typename bmupd::enable_up_moveconv_assign ::type) operator=(BOOST_RV_REF_BEG unique_ptr BOOST_RV_REF_END u) BOOST_NOEXCEPT { @@ -720,7 +573,7 @@ class unique_ptr //! Postcondition: get() == nullptr //! //! Returns: *this. - unique_ptr& operator=(BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) BOOST_NOEXCEPT + unique_ptr& operator=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT { this->reset(); return *this; } //! Requires: get() != nullptr. @@ -728,10 +581,10 @@ class unique_ptr //! Returns: *get(). //! //! Remarks::type) + BOOST_MOVE_DOC1ST(element_type&, typename bmupmu::add_lvalue_reference::type) operator*() const BOOST_NOEXCEPT { - BOOST_STATIC_ASSERT((!bmd::is_array::value)); + BOOST_STATIC_ASSERT((!bmupmu::is_array::value)); return *m_data.m_p; } @@ -740,10 +593,10 @@ class unique_ptr //! Returns: get()[i]. //! //! Remarks::type) + BOOST_MOVE_DOC1ST(element_type&, typename bmupmu::add_lvalue_reference::type) operator[](std::size_t i) const BOOST_NOEXCEPT { - BOOST_ASSERT( bmd::extent::value == 0 || i < bmd::extent::value ); + BOOST_ASSERT( bmupmu::extent::value == 0 || i < bmupmu::extent::value ); BOOST_ASSERT(m_data.m_p); return m_data.m_p[i]; } @@ -757,7 +610,7 @@ class unique_ptr //! Remarks() const BOOST_NOEXCEPT { - BOOST_STATIC_ASSERT((!bmd::is_array::value)); + BOOST_STATIC_ASSERT((!bmupmu::is_array::value)); BOOST_ASSERT(m_data.m_p); return m_data.m_p; } @@ -769,13 +622,13 @@ class unique_ptr //! Returns: A reference to the stored deleter. //! - BOOST_MOVE_DOC1ST(D&, typename bmd::add_lvalue_reference::type) + BOOST_MOVE_DOC1ST(D&, typename bmupmu::add_lvalue_reference::type) get_deleter() BOOST_NOEXCEPT { return m_data.deleter(); } //! Returns: A reference to the stored deleter. //! - BOOST_MOVE_DOC1ST(const D&, typename bmd::add_const_lvalue_reference::type) + BOOST_MOVE_DOC1ST(const D&, typename bmupmu::add_const_lvalue_reference::type) get_deleter() const BOOST_NOEXCEPT { return m_data.deleter(); } @@ -784,13 +637,13 @@ class unique_ptr //! explicit operator bool #else - operator bmd::explicit_bool_arg + operator bmupd::explicit_bool_arg #endif ()const BOOST_NOEXCEPT { return m_data.m_p - ? &bmd::bool_conversion::for_bool - : bmd::explicit_bool_arg(0); + ? &bmupd::bool_conversion::for_bool + : bmupd::explicit_bool_arg(0); } //! Postcondition: get() == nullptr. @@ -817,7 +670,7 @@ class unique_ptr //! - If T is not an array type and Pointer is implicitly convertible to pointer. //! - If T is an array type and Pointer is a more CV qualified pointer to element_type. template - BOOST_MOVE_DOC1ST(void, typename bmd::enable_up_ptr::type) + BOOST_MOVE_DOC1ST(void, typename bmupd::enable_up_ptr::type) reset(Pointer p) BOOST_NOEXCEPT { pointer tmp = m_data.m_p; @@ -839,7 +692,7 @@ class unique_ptr //! Effects: Same as reset() //! - void reset(BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) BOOST_NOEXCEPT + void reset(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT { this->reset(); } //! Requires: get_deleter() shall be swappable and shall not throw an exception under swap. @@ -847,7 +700,7 @@ class unique_ptr //! Effects: Invokes swap on the stored pointers and on the stored deleters of *this and u. void swap(unique_ptr& u) BOOST_NOEXCEPT { - using bmd::swap; + using bmupmu::swap; swap(m_data.m_p, u.m_data.m_p); swap(m_data.deleter(), u.m_data.deleter()); } @@ -900,76 +753,76 @@ inline bool operator>=(const unique_ptr &x, const unique_ptr &y) //! Returns:!x. //! template -inline bool operator==(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) BOOST_NOEXCEPT +inline bool operator==(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT { return !x; } //! Returns:!x. //! template -inline bool operator==(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr &x) BOOST_NOEXCEPT +inline bool operator==(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr &x) BOOST_NOEXCEPT { return !x; } //! Returns: (bool)x. //! template -inline bool operator!=(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) BOOST_NOEXCEPT +inline bool operator!=(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) BOOST_NOEXCEPT { return !!x; } //! Returns: (bool)x. //! template -inline bool operator!=(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr &x) BOOST_NOEXCEPT +inline bool operator!=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr &x) BOOST_NOEXCEPT { return !!x; } //! Requires: operator shall induce a strict weak ordering on unique_ptr::pointer values. //! //! Returns: Returns x.get() < pointer(). template -inline bool operator<(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) +inline bool operator<(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) { return x.get() < typename unique_ptr::pointer(); } //! Requires: operator shall induce a strict weak ordering on unique_ptr::pointer values. //! //! Returns: Returns pointer() < x.get(). template -inline bool operator<(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr &x) +inline bool operator<(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr &x) { return typename unique_ptr::pointer() < x.get(); } //! Returns: nullptr < x. //! template -inline bool operator>(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) +inline bool operator>(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) { return x.get() > typename unique_ptr::pointer(); } //! Returns: x < nullptr. //! template -inline bool operator>(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr &x) +inline bool operator>(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr &x) { return typename unique_ptr::pointer() > x.get(); } //! Returns: !(nullptr < x). //! template -inline bool operator<=(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) -{ return !(bmd::nullptr_type() < x); } +inline bool operator<=(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) +{ return !(bmupd::nullptr_type() < x); } //! Returns: !(x < nullptr). //! template -inline bool operator<=(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr &x) -{ return !(x < bmd::nullptr_type()); } +inline bool operator<=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr &x) +{ return !(x < bmupd::nullptr_type()); } //! Returns: !(x < nullptr). //! template -inline bool operator>=(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmd::nullptr_type)) -{ return !(x < bmd::nullptr_type()); } +inline bool operator>=(const unique_ptr &x, BOOST_MOVE_DOC0PTR(bmupd::nullptr_type)) +{ return !(x < bmupd::nullptr_type()); } //! Returns: !(nullptr < x). //! template -inline bool operator>=(BOOST_MOVE_DOC0PTR(bmd::nullptr_type), const unique_ptr &x) -{ return !(bmd::nullptr_type() < x); } +inline bool operator>=(BOOST_MOVE_DOC0PTR(bmupd::nullptr_type), const unique_ptr &x) +{ return !(bmupd::nullptr_type() < x); } } //namespace movelib { } //namespace boost{ diff --git a/proj/vc7ide/Move.sln b/proj/vc7ide/Move.sln index e9d250b..b43ac07 100644 --- a/proj/vc7ide/Move.sln +++ b/proj/vc7ide/Move.sln @@ -95,7 +95,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unique_ptr_nullptr_test", " ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unique_ptr_test", "unique_ptr_observers_test.vcproj", "{C57C28A3-4FE0-6208-BF87-B2B61D3A7670}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unique_ptr_observers_test", "unique_ptr_observers_test.vcproj", "{C57C28A3-4FE0-6208-BF87-B2B61D3A7670}" ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject @@ -221,6 +221,7 @@ Global ..\..\..\..\boost\move\detail\config_begin.hpp = ..\..\..\..\boost\move\detail\config_begin.hpp ..\..\..\..\boost\move\detail\config_end.hpp = ..\..\..\..\boost\move\detail\config_end.hpp ..\..\..\..\boost\move\core.hpp = ..\..\..\..\boost\move\core.hpp + ..\..\..\..\boost\move\default_delete.hpp = ..\..\..\..\boost\move\default_delete.hpp ..\..\..\..\boost\move\iterator.hpp = ..\..\..\..\boost\move\iterator.hpp ..\..\doc\Jamfile.v2 = ..\..\doc\Jamfile.v2 ..\..\..\..\boost\move\make_unique.hpp = ..\..\..\..\boost\move\make_unique.hpp diff --git a/test/unique_ptr_default_deleter.cpp b/test/unique_ptr_default_deleter.cpp index cbe6255..67b36ea 100644 --- a/test/unique_ptr_default_deleter.cpp +++ b/test/unique_ptr_default_deleter.cpp @@ -10,7 +10,7 @@ // See http://www.boost.org/libs/move for documentation. // ////////////////////////////////////////////////////////////////////////////// -#include +#include #include ////////////////////////////////////////////// diff --git a/test/unique_ptr_movector.cpp b/test/unique_ptr_movector.cpp index b8d7aa7..ece216b 100644 --- a/test/unique_ptr_movector.cpp +++ b/test/unique_ptr_movector.cpp @@ -32,6 +32,7 @@ #include "unique_ptr_test_utils_beg.hpp" namespace bml = ::boost::movelib; +namespace bmupmu = ::boost::move_upmu; //////////////////////////////// // unique_ptr_ctor_move_defdel @@ -266,7 +267,7 @@ void test() { //Single unique_ptr reset_counters(); - BOOST_STATIC_ASSERT((boost::move_detail::is_convertible::value)); + BOOST_STATIC_ASSERT((bmupmu::is_convertible::value)); { bml::unique_ptr > s(new B); A* p = s.get(); diff --git a/test/unique_ptr_test_utils_beg.hpp b/test/unique_ptr_test_utils_beg.hpp index 51995f5..a98e926 100644 --- a/test/unique_ptr_test_utils_beg.hpp +++ b/test/unique_ptr_test_utils_beg.hpp @@ -71,13 +71,13 @@ class copy_constr_deleter template copy_constr_deleter(const copy_constr_deleter& - , typename boost::move_detail::enable_def_del::type* =0) + , typename boost::move_upd::enable_def_del::type* =0) { state_ = 5; } explicit copy_constr_deleter(int s) : state_(s) {} template - typename boost::move_detail::enable_def_del::type + typename boost::move_upd::enable_def_del::type operator=(const copy_constr_deleter &d) { state_ = d.state(); @@ -117,7 +117,7 @@ class move_constr_deleter template move_constr_deleter(BOOST_RV_REF(move_constr_deleter) d - , typename boost::move_detail::enable_def_del::type* =0) + , typename boost::move_upd::enable_def_del::type* =0) : state_(d.state()) { d.set_state(0); } @@ -129,7 +129,7 @@ class move_constr_deleter } template - typename boost::move_detail::enable_def_del::type + typename boost::move_upd::enable_def_del::type operator=(BOOST_RV_REF(move_constr_deleter) d) { state_ = d.state(); diff --git a/test/unique_ptr_types.cpp b/test/unique_ptr_types.cpp index 6d7d4a8..484c906 100644 --- a/test/unique_ptr_types.cpp +++ b/test/unique_ptr_types.cpp @@ -32,6 +32,7 @@ #include "unique_ptr_test_utils_beg.hpp" namespace bml = ::boost::movelib; +namespace bmupmu = ::boost::move_upmu; //////////////////////////////// // unique_ptr_pointer_type @@ -49,29 +50,29 @@ void test() //Single unique_ptr { typedef bml::unique_ptr P; - BOOST_STATIC_ASSERT((boost::move_detail::is_same::value)); + BOOST_STATIC_ASSERT((bmupmu::is_same::value)); } { typedef bml::unique_ptr P; - BOOST_STATIC_ASSERT((boost::move_detail::is_same::value)); + BOOST_STATIC_ASSERT((bmupmu::is_same::value)); } //Unbounded array unique_ptr { typedef bml::unique_ptr P; - BOOST_STATIC_ASSERT((boost::move_detail::is_same::value)); + BOOST_STATIC_ASSERT((bmupmu::is_same::value)); } { typedef bml::unique_ptr P; - BOOST_STATIC_ASSERT((boost::move_detail::is_same::value)); + BOOST_STATIC_ASSERT((bmupmu::is_same::value)); } //Bounded array unique_ptr { typedef bml::unique_ptr P; - BOOST_STATIC_ASSERT((boost::move_detail::is_same::value)); + BOOST_STATIC_ASSERT((bmupmu::is_same::value)); } { typedef bml::unique_ptr P; - BOOST_STATIC_ASSERT((boost::move_detail::is_same::value)); + BOOST_STATIC_ASSERT((bmupmu::is_same::value)); } } @@ -91,29 +92,29 @@ void test() //Single unique_ptr { typedef bml::unique_ptr P; - BOOST_STATIC_ASSERT((boost::move_detail::is_same >::value)); + BOOST_STATIC_ASSERT((bmupmu::is_same >::value)); } { typedef bml::unique_ptr P; - BOOST_STATIC_ASSERT((boost::move_detail::is_same::value)); + BOOST_STATIC_ASSERT((bmupmu::is_same::value)); } //Unbounded array unique_ptr { typedef bml::unique_ptr P; - BOOST_STATIC_ASSERT((boost::move_detail::is_same >::value)); + BOOST_STATIC_ASSERT((bmupmu::is_same >::value)); } { typedef bml::unique_ptr P; - BOOST_STATIC_ASSERT((boost::move_detail::is_same::value)); + BOOST_STATIC_ASSERT((bmupmu::is_same::value)); } //Bounded array unique_ptr { typedef bml::unique_ptr P; - BOOST_STATIC_ASSERT((boost::move_detail::is_same >::value)); + BOOST_STATIC_ASSERT((bmupmu::is_same >::value)); } { typedef bml::unique_ptr P; - BOOST_STATIC_ASSERT((boost::move_detail::is_same::value)); + BOOST_STATIC_ASSERT((bmupmu::is_same::value)); } } @@ -130,17 +131,17 @@ void test() //Single unique_ptr { typedef bml::unique_ptr P; - BOOST_STATIC_ASSERT((boost::move_detail::is_same::value)); + BOOST_STATIC_ASSERT((bmupmu::is_same::value)); } //Unbounded array unique_ptr { typedef bml::unique_ptr P; - BOOST_STATIC_ASSERT((boost::move_detail::is_same::value)); + BOOST_STATIC_ASSERT((bmupmu::is_same::value)); } //Bounded array unique_ptr { typedef bml::unique_ptr P; - BOOST_STATIC_ASSERT((boost::move_detail::is_same::value)); + BOOST_STATIC_ASSERT((bmupmu::is_same::value)); } } From 7349db265a79a99e9ed9e83a4a2460c1ff1ee181 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Tue, 2 Sep 2014 23:34:53 +0200 Subject: [PATCH 08/10] Fixed typo in assignment test --- test/unique_ptr_default_deleter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unique_ptr_default_deleter.cpp b/test/unique_ptr_default_deleter.cpp index 67b36ea..35563f9 100644 --- a/test/unique_ptr_default_deleter.cpp +++ b/test/unique_ptr_default_deleter.cpp @@ -91,7 +91,7 @@ void test() const A* p = new const A[2]; BOOST_TEST(A::count == 2); d1(p); - bml::default_delete d0 = d1; + bml::default_delete d0 = d1; d0(0); BOOST_TEST(A::count == 0); } From 3075014f2dd78f369e099e2b4e98629d89fc8ae0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 4 Sep 2014 00:15:56 +0200 Subject: [PATCH 09/10] Added check for types with no virtual destructor when using default_delete and non-array types --- include/boost/move/default_delete.hpp | 16 ++++- .../move/detail/unique_ptr_meta_utils.hpp | 69 ++++++++++++++++++- include/boost/move/unique_ptr.hpp | 29 +++++++- proj/vc7ide/Move.sln | 1 + 4 files changed, 109 insertions(+), 6 deletions(-) diff --git a/include/boost/move/default_delete.hpp b/include/boost/move/default_delete.hpp index dab8a83..d8ad360 100644 --- a/include/boost/move/default_delete.hpp +++ b/include/boost/move/default_delete.hpp @@ -128,7 +128,11 @@ struct default_delete default_delete(const default_delete& BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_def_del::type* =0) ) BOOST_NOEXCEPT - {} + { + //If T is not an array type, U derives from T + //and T has no virtual destructor, then you have a problem + BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor::value )); + } //! Effects: Constructs a default_delete object from another default_delete object. //! @@ -139,7 +143,12 @@ struct default_delete BOOST_MOVE_DOC1ST(default_delete&, typename bmupd::enable_def_del::type) operator=(const default_delete&) BOOST_NOEXCEPT - { return *this; } + { + //If T is not an array type, U derives from T + //and T has no virtual destructor, then you have a problem + BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor::value )); + return *this; + } //! Effects: if T is not an array type, calls delete on static_cast(ptr), //! otherwise calls delete[] on static_cast::type*>(ptr). @@ -155,6 +164,9 @@ struct default_delete { //U must be a complete type BOOST_STATIC_ASSERT(sizeof(U) > 0); + //If T is not an array type, U derives from T + //and T has no virtual destructor, then you have a problem + BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor::value )); element_type * const p = static_cast(ptr); bmupmu::is_array::value ? delete [] p : delete p; } diff --git a/include/boost/move/detail/unique_ptr_meta_utils.hpp b/include/boost/move/detail/unique_ptr_meta_utils.hpp index 33e4d52..89143a7 100644 --- a/include/boost/move/detail/unique_ptr_meta_utils.hpp +++ b/include/boost/move/detail/unique_ptr_meta_utils.hpp @@ -20,6 +20,13 @@ namespace boost { +namespace movelib { + +template +struct default_delete; + +} //namespace movelib { + #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES //Forward declare boost::rv template class rv; @@ -423,7 +430,7 @@ class is_convertible #endif ////////////////////////////////////// -// is_unary_function +// is_unary_function ////////////////////////////////////// #if defined(BOOST_MSVC) || defined(__BORLANDC_) #define BOOST_MOVE_TT_DECL __cdecl @@ -517,6 +524,66 @@ template struct is_unary_function { static const bool value = is_unary_function_impl::value; }; +////////////////////////////////////// +// has_virtual_destructor +////////////////////////////////////// +#if (defined(BOOST_MSVC) && defined(BOOST_MSVC_FULL_VER) && (BOOST_MSVC_FULL_VER >=140050215))\ + || (defined(BOOST_INTEL) && defined(_MSC_VER) && (_MSC_VER >= 1500)) +# define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T) +#elif defined(BOOST_CLANG) && defined(__has_feature) +# if __has_feature(has_virtual_destructor) +# define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T) +# endif +#elif defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3) && !defined(__GCCXML__))) && !defined(BOOST_CLANG) +# define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T) +#elif defined(__ghs__) && (__GHS_VERSION_NUMBER >= 600) +# define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T) +#elif defined(__CODEGEARC__) +# define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T) +#endif + +#ifdef BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR + template + struct has_virtual_destructor{ static const bool value = BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T); }; +#else + //If no intrinsic is available you trust the programmer knows what is doing + template + struct has_virtual_destructor{ static const bool value = true; }; +#endif + +////////////////////////////////////// +// missing_virtual_destructor +////////////////////////////////////// + +template< class T, class U + , bool enable = is_convertible< typename remove_cv::type* + , typename remove_cv::type*>::value && + !is_array::value && + !is_same::type, void>::value && + !is_same::type, typename remove_cv::type>::value + > +struct missing_virtual_destructor_default_delete +{ + static const bool value = !has_virtual_destructor::value; +}; + +template +struct missing_virtual_destructor_default_delete +{ + static const bool value = false; +}; + +template +struct missing_virtual_destructor +{ + static const bool value = false; +}; + +template +struct missing_virtual_destructor< ::boost::movelib::default_delete, U > + : missing_virtual_destructor_default_delete +{}; + } //namespace move_upmu { } //namespace boost { diff --git a/include/boost/move/unique_ptr.hpp b/include/boost/move/unique_ptr.hpp index a78ca66..be74a1f 100644 --- a/include/boost/move/unique_ptr.hpp +++ b/include/boost/move/unique_ptr.hpp @@ -411,6 +411,10 @@ class unique_ptr ) BOOST_NOEXCEPT : m_data(p) { + //If T is not an array type, element_type_t derives from T + //it uses the default deleter and T has no virtual destructor, then you have a problem + BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor + ::type>::value )); //If this constructor is instantiated with a pointer type or reference type //for the template argument D, the program is ill-formed. BOOST_STATIC_ASSERT(!bmupmu::is_pointer::value); @@ -444,7 +448,12 @@ class unique_ptr BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_ptr::type* =0) ) BOOST_NOEXCEPT : m_data(p, d1) - {} + { + //If T is not an array type, element_type_t derives from T + //it uses the default deleter and T has no virtual destructor, then you have a problem + BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor + ::type>::value )); + } //! Effects: Same effects as template unique_ptr(Pointer p, deleter_arg_type1 d1) //! and additionally get() == nullptr @@ -477,7 +486,12 @@ class unique_ptr BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_ptr::type* =0) ) BOOST_NOEXCEPT : m_data(p, ::boost::move(d2)) - {} + { + //If T is not an array type, element_type_t derives from T + //it uses the default deleter and T has no virtual destructor, then you have a problem + BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor + ::type>::value )); + } //! Effects: Same effects as template unique_ptr(Pointer p, deleter_arg_type2 d2) //! and additionally get() == nullptr @@ -519,7 +533,12 @@ class unique_ptr BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_moveconv_constr::type* =0) ) BOOST_NOEXCEPT : m_data(u.release(), ::boost::move_if_not_lvalue_reference(u.get_deleter())) - {} + { + //If T is not an array type, U derives from T + //it uses the default deleter and T has no virtual destructor, then you have a problem + BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor + ::pointer>::value )); + } //! Requires: The expression get_deleter()(get()) shall be well formed, shall have well-defined behavior, //! and shall not throw exceptions. @@ -673,6 +692,10 @@ class unique_ptr BOOST_MOVE_DOC1ST(void, typename bmupd::enable_up_ptr::type) reset(Pointer p) BOOST_NOEXCEPT { + //If T is not an array type, element_type_t derives from T + //it uses the default deleter and T has no virtual destructor, then you have a problem + BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor + ::type>::value )); pointer tmp = m_data.m_p; m_data.m_p = p; if(tmp) m_data.deleter()(tmp); diff --git a/proj/vc7ide/Move.sln b/proj/vc7ide/Move.sln index b43ac07..c12681b 100644 --- a/proj/vc7ide/Move.sln +++ b/proj/vc7ide/Move.sln @@ -231,6 +231,7 @@ Global ..\..\..\..\boost\move\detail\move_helpers.hpp = ..\..\..\..\boost\move\detail\move_helpers.hpp ..\..\..\..\boost\move\traits.hpp = ..\..\..\..\boost\move\traits.hpp ..\..\..\..\boost\move\unique_ptr.hpp = ..\..\..\..\boost\move\unique_ptr.hpp + ..\..\..\..\boost\move\detail\unique_ptr_meta_utils.hpp = ..\..\..\..\boost\move\detail\unique_ptr_meta_utils.hpp ..\..\test\unique_ptr_test_utils_beg.hpp = ..\..\test\unique_ptr_test_utils_beg.hpp ..\..\test\unique_ptr_test_utils_end.hpp = ..\..\test\unique_ptr_test_utils_end.hpp ..\..\..\..\boost\move\utility.hpp = ..\..\..\..\boost\move\utility.hpp From 65c8c63ddb7f6b1e4eb0440c3bbba1ab335cea34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 4 Sep 2014 00:24:44 +0200 Subject: [PATCH 10/10] Fixed is_convertible bug in missing_virtual_destructor --- .../boost/move/detail/unique_ptr_meta_utils.hpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/include/boost/move/detail/unique_ptr_meta_utils.hpp b/include/boost/move/detail/unique_ptr_meta_utils.hpp index 89143a7..42fd272 100644 --- a/include/boost/move/detail/unique_ptr_meta_utils.hpp +++ b/include/boost/move/detail/unique_ptr_meta_utils.hpp @@ -556,28 +556,21 @@ struct is_unary_function ////////////////////////////////////// template< class T, class U - , bool enable = is_convertible< typename remove_cv::type* - , typename remove_cv::type*>::value && + , bool enable = is_convertible< U*, T*>::value && !is_array::value && !is_same::type, void>::value && !is_same::type, typename remove_cv::type>::value > struct missing_virtual_destructor_default_delete -{ - static const bool value = !has_virtual_destructor::value; -}; +{ static const bool value = !has_virtual_destructor::value; }; template struct missing_virtual_destructor_default_delete -{ - static const bool value = false; -}; +{ static const bool value = false; }; template struct missing_virtual_destructor -{ - static const bool value = false; -}; +{ static const bool value = false; }; template struct missing_virtual_destructor< ::boost::movelib::default_delete, U >