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"