diff --git a/include/boost/move/make_unique.hpp b/include/boost/move/make_unique.hpp index 4a4f99a..59cfafa 100644 --- a/include/boost/move/make_unique.hpp +++ b/include/boost/move/make_unique.hpp @@ -25,10 +25,15 @@ //! This header can be a bit heavyweight in C++03 compilers due to the use of the //! preprocessor library, that's why it's a a separate header from unique_ptr.hpp -namespace boost{ - #if !defined(BOOST_MOVE_DOXYGEN_INVOKED) +namespace std { //no namespace versioning in clang+libc++ + +struct nothrow_t; + +} //namespace std { + +namespace boost{ namespace move_upmu { //Compile time switch between @@ -52,10 +57,14 @@ struct unique_ptr_if typedef void t_is_array_of_known_bound; }; +static std::nothrow_t *pnothrow; + } //namespace move_upmu { +} //namespace boost{ #endif //!defined(BOOST_MOVE_DOXYGEN_INVOKED) +namespace boost{ namespace movelib { #if defined(BOOST_MOVE_DOXYGEN_INVOKED) || !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) @@ -69,6 +78,15 @@ inline BOOST_MOVE_DOC1ST(unique_ptr, make_unique(BOOST_FWD_REF(Args)... args) { return unique_ptr(new T(::boost::forward(args)...)); } +//! Remarks: This function shall not participate in overload resolution unless T is not an array. +//! +//! Returns: unique_ptr(new T(std::nothrow)(std::forward(args)...)). +template +inline BOOST_MOVE_DOC1ST(unique_ptr, + typename ::boost::move_upmu::unique_ptr_if::t_is_not_array) + make_unique_nothrow(BOOST_FWD_REF(Args)... args) +{ return unique_ptr(new (*boost::move_upmu::pnothrow)T(::boost::forward(args)...)); } + #else //0 arg @@ -76,6 +94,12 @@ inline BOOST_MOVE_DOC1ST(unique_ptr, typename ::boost::move_upmu::unique_ptr_if::t_is_not_array make_unique() { return unique_ptr(new T()); } + + template + typename ::boost::move_upmu::unique_ptr_if::t_is_not_array + make_unique_nothrow() + { return unique_ptr(new (*boost::move_upmu::pnothrow)T()); } + //1 arg template typename ::boost::move_upmu::unique_ptr_if::t_is_not_array @@ -87,6 +111,17 @@ inline BOOST_MOVE_DOC1ST(unique_ptr, ) ); } + + template + typename ::boost::move_upmu::unique_ptr_if::t_is_not_array + make_unique_nothrow( BOOST_FWD_REF(P0) p0 + ) + { + return unique_ptr + ( new (*boost::move_upmu::pnothrow)T ( ::boost::forward(p0) + ) + ); + } //2 arg template typename ::boost::move_upmu::unique_ptr_if::t_is_not_array @@ -100,6 +135,19 @@ inline BOOST_MOVE_DOC1ST(unique_ptr, ) ); } + + template + typename ::boost::move_upmu::unique_ptr_if::t_is_not_array + make_unique_nothrow( BOOST_FWD_REF(P0) p0 + , BOOST_FWD_REF(P1) p1 + ) + { + return unique_ptr + ( new (*boost::move_upmu::pnothrow)T ( ::boost::forward(p0) + , ::boost::forward(p1) + ) + ); + } //3 arg template typename ::boost::move_upmu::unique_ptr_if::t_is_not_array @@ -115,6 +163,21 @@ inline BOOST_MOVE_DOC1ST(unique_ptr, ) ); } + + template + typename ::boost::move_upmu::unique_ptr_if::t_is_not_array + make_unique_nothrow ( BOOST_FWD_REF(P0) p0 + , BOOST_FWD_REF(P1) p1 + , BOOST_FWD_REF(P2) p2 + ) + { + return unique_ptr + ( new (*boost::move_upmu::pnothrow)T ( ::boost::forward(p0) + , ::boost::forward(p1) + , ::boost::forward(p2) + ) + ); + } //4 arg template typename ::boost::move_upmu::unique_ptr_if::t_is_not_array @@ -132,6 +195,23 @@ inline BOOST_MOVE_DOC1ST(unique_ptr, ) ); } + + template + typename ::boost::move_upmu::unique_ptr_if::t_is_not_array + make_unique_nothrow ( BOOST_FWD_REF(P0) p0 + , BOOST_FWD_REF(P1) p1 + , BOOST_FWD_REF(P2) p2 + , BOOST_FWD_REF(P3) p3 + ) + { + return unique_ptr + ( new (*boost::move_upmu::pnothrow)T ( ::boost::forward(p0) + , ::boost::forward(p1) + , ::boost::forward(p2) + , ::boost::forward(p3) + ) + ); + } //5 arg template typename ::boost::move_upmu::unique_ptr_if::t_is_not_array @@ -151,6 +231,25 @@ inline BOOST_MOVE_DOC1ST(unique_ptr, ) ); } + + template + typename ::boost::move_upmu::unique_ptr_if::t_is_not_array + make_unique_nothrow ( BOOST_FWD_REF(P0) p0 + , BOOST_FWD_REF(P1) p1 + , BOOST_FWD_REF(P2) p2 + , BOOST_FWD_REF(P3) p3 + , BOOST_FWD_REF(P4) p4 + ) + { + return unique_ptr + ( new (*boost::move_upmu::pnothrow)T ( ::boost::forward(p0) + , ::boost::forward(p1) + , ::boost::forward(p2) + , ::boost::forward(p3) + , ::boost::forward(p4) + ) + ); + } //6 arg template typename ::boost::move_upmu::unique_ptr_if::t_is_not_array @@ -172,6 +271,27 @@ inline BOOST_MOVE_DOC1ST(unique_ptr, ) ); } + + template + typename ::boost::move_upmu::unique_ptr_if::t_is_not_array + make_unique_nothrow ( BOOST_FWD_REF(P0) p0 + , BOOST_FWD_REF(P1) p1 + , BOOST_FWD_REF(P2) p2 + , BOOST_FWD_REF(P3) p3 + , BOOST_FWD_REF(P4) p4 + , BOOST_FWD_REF(P5) p5 + ) + { + return unique_ptr + ( new (*boost::move_upmu::pnothrow)T ( ::boost::forward(p0) + , ::boost::forward(p1) + , ::boost::forward(p2) + , ::boost::forward(p3) + , ::boost::forward(p4) + , ::boost::forward(p5) + ) + ); + } //7 arg template typename ::boost::move_upmu::unique_ptr_if::t_is_not_array @@ -195,6 +315,30 @@ inline BOOST_MOVE_DOC1ST(unique_ptr, ) ); } + + template + typename ::boost::move_upmu::unique_ptr_if::t_is_not_array + make_unique_nothrow ( BOOST_FWD_REF(P0) p0 + , BOOST_FWD_REF(P1) p1 + , BOOST_FWD_REF(P2) p2 + , BOOST_FWD_REF(P3) p3 + , BOOST_FWD_REF(P4) p4 + , BOOST_FWD_REF(P5) p5 + , BOOST_FWD_REF(P6) p6 + ) + { + return unique_ptr + ( new (*boost::move_upmu::pnothrow)T ( ::boost::forward(p0) + , ::boost::forward(p1) + , ::boost::forward(p2) + , ::boost::forward(p3) + , ::boost::forward(p4) + , ::boost::forward(p5) + , ::boost::forward(p6) + ) + ); + } + //8 arg template typename ::boost::move_upmu::unique_ptr_if::t_is_not_array @@ -220,6 +364,31 @@ inline BOOST_MOVE_DOC1ST(unique_ptr, ) ); } + + template + typename ::boost::move_upmu::unique_ptr_if::t_is_not_array + make_unique_nothrow ( BOOST_FWD_REF(P0) p0 + , BOOST_FWD_REF(P1) p1 + , BOOST_FWD_REF(P2) p2 + , BOOST_FWD_REF(P3) p3 + , BOOST_FWD_REF(P4) p4 + , BOOST_FWD_REF(P5) p5 + , BOOST_FWD_REF(P6) p6 + , BOOST_FWD_REF(P7) p7 + ) + { + return unique_ptr + ( new (*boost::move_upmu::pnothrow)T ( ::boost::forward(p0) + , ::boost::forward(p1) + , ::boost::forward(p2) + , ::boost::forward(p3) + , ::boost::forward(p4) + , ::boost::forward(p5) + , ::boost::forward(p6) + , ::boost::forward(p7) + ) + ); + } //9 arg template typename ::boost::move_upmu::unique_ptr_if::t_is_not_array @@ -247,6 +416,33 @@ inline BOOST_MOVE_DOC1ST(unique_ptr, ) ); } + + template + typename ::boost::move_upmu::unique_ptr_if::t_is_not_array + make_unique_nothrow ( BOOST_FWD_REF(P0) p0 + , BOOST_FWD_REF(P1) p1 + , BOOST_FWD_REF(P2) p2 + , BOOST_FWD_REF(P3) p3 + , BOOST_FWD_REF(P4) p4 + , BOOST_FWD_REF(P5) p5 + , BOOST_FWD_REF(P6) p6 + , BOOST_FWD_REF(P7) p7 + , BOOST_FWD_REF(P8) p8 + ) + { + return unique_ptr + ( new (*boost::move_upmu::pnothrow)T ( ::boost::forward(p0) + , ::boost::forward(p1) + , ::boost::forward(p2) + , ::boost::forward(p3) + , ::boost::forward(p4) + , ::boost::forward(p5) + , ::boost::forward(p6) + , ::boost::forward(p7) + , ::boost::forward(p8) + ) + ); + } //10 arg template typename ::boost::move_upmu::unique_ptr_if::t_is_not_array @@ -277,6 +473,35 @@ inline BOOST_MOVE_DOC1ST(unique_ptr, ); } + template + typename ::boost::move_upmu::unique_ptr_if::t_is_not_array + make_unique_nothrow ( BOOST_FWD_REF(P0) p0 + , BOOST_FWD_REF(P1) p1 + , BOOST_FWD_REF(P2) p2 + , BOOST_FWD_REF(P3) p3 + , BOOST_FWD_REF(P4) p4 + , BOOST_FWD_REF(P5) p5 + , BOOST_FWD_REF(P6) p6 + , BOOST_FWD_REF(P7) p7 + , BOOST_FWD_REF(P8) p8 + , BOOST_FWD_REF(P9) p9 + ) + { + return unique_ptr + ( new (*boost::move_upmu::pnothrow)T ( ::boost::forward(p0) + , ::boost::forward(p1) + , ::boost::forward(p2) + , ::boost::forward(p3) + , ::boost::forward(p4) + , ::boost::forward(p5) + , ::boost::forward(p6) + , ::boost::forward(p7) + , ::boost::forward(p8) + , ::boost::forward(p9) + ) + ); + } + #endif //! Remarks: This function shall not participate in overload resolution unless T is not an array. @@ -290,6 +515,17 @@ inline BOOST_MOVE_DOC1ST(unique_ptr, return unique_ptr(new T); } +//! Remarks: This function shall not participate in overload resolution unless T is not an array. +//! +//! Returns: unique_ptr(new T(std::nothrow) (default initialization) +template +inline BOOST_MOVE_DOC1ST(unique_ptr, + typename ::boost::move_upmu::unique_ptr_if::t_is_not_array) + make_unique_nothrow_definit() +{ + return unique_ptr(new (*boost::move_upmu::pnothrow)T); +} + //! Remarks: This function shall not participate in overload resolution unless T is an array of //! unknown bound. //! @@ -303,6 +539,19 @@ inline BOOST_MOVE_DOC1ST(unique_ptr, return unique_ptr(new U[n]()); } +//! Remarks: This function shall not participate in overload resolution unless T is an array of +//! unknown bound. +//! +//! Returns: unique_ptr(new (std::nothrow)remove_extent_t[n]()) (value initialization) +template +inline BOOST_MOVE_DOC1ST(unique_ptr, + typename ::boost::move_upmu::unique_ptr_if::t_is_array_of_unknown_bound) + make_unique_nothrow(std::size_t n) +{ + typedef typename ::boost::move_upmu::remove_extent::type U; + return unique_ptr(new (*boost::move_upmu::pnothrow)U[n]()); +} + //! Remarks: This function shall not participate in overload resolution unless T is an array of //! unknown bound. //! @@ -316,6 +565,19 @@ inline BOOST_MOVE_DOC1ST(unique_ptr, return unique_ptr(new U[n]); } +//! Remarks: This function shall not participate in overload resolution unless T is an array of +//! unknown bound. +//! +//! Returns: unique_ptr(new (std::nothrow)remove_extent_t[n]) (default initialization) +template +inline BOOST_MOVE_DOC1ST(unique_ptr, + typename ::boost::move_upmu::unique_ptr_if::t_is_array_of_unknown_bound) + make_unique_nothrow_definit(std::size_t n) +{ + typedef typename ::boost::move_upmu::remove_extent::type U; + return unique_ptr(new (*boost::move_upmu::pnothrow) U[n]); +} + #if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) //! Remarks: This function shall not participate in overload resolution unless T is @@ -324,6 +586,28 @@ template inline BOOST_MOVE_DOC1ST(unspecified, typename ::boost::move_upmu::unique_ptr_if::t_is_array_of_known_bound) make_unique(BOOST_FWD_REF(Args) ...) = delete; + +//! Remarks: This function shall not participate in overload resolution unless T is +//! an array of known bound. +template +inline BOOST_MOVE_DOC1ST(unspecified, + typename ::boost::move_upmu::unique_ptr_if::t_is_array_of_known_bound) + make_unique_definit(BOOST_FWD_REF(Args) ...) = delete; + +//! Remarks: This function shall not participate in overload resolution unless T is +//! an array of known bound. +template +inline BOOST_MOVE_DOC1ST(unspecified, + typename ::boost::move_upmu::unique_ptr_if::t_is_array_of_known_bound) + make_unique_nothrow(BOOST_FWD_REF(Args) ...) = delete; + +//! Remarks: This function shall not participate in overload resolution unless T is +//! an array of known bound. +template +inline BOOST_MOVE_DOC1ST(unspecified, + typename ::boost::move_upmu::unique_ptr_if::t_is_array_of_known_bound) + make_unique_nothrow_definit(BOOST_FWD_REF(Args) ...) = delete; + #endif } //namespace movelib { diff --git a/test/unique_ptr_functions.cpp b/test/unique_ptr_functions.cpp index 21dc99c..33274d2 100644 --- a/test/unique_ptr_functions.cpp +++ b/test/unique_ptr_functions.cpp @@ -44,6 +44,8 @@ void reset_counters() 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 }; +static const unsigned char dd_patternbuf[PatternSize] = { 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD }; +static const unsigned char cc_patternbuf[PatternSize] = { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC }; struct default_init { @@ -57,6 +59,16 @@ struct default_init void *const p = ::operator new[](sz); return std::memset(p, 0xEE, sz); } + static void* operator new(std::size_t sz, const std::nothrow_t &) + { + void *const p = ::operator new(sz); + return std::memset(p, 0xDD, sz); + } + static void* operator new[](std::size_t sz, const std::nothrow_t &) + { + void *const p = ::operator new[](sz); + return std::memset(p, 0xCC, sz); + } unsigned char buf[PatternSize]; }; @@ -78,6 +90,11 @@ void test() bml::unique_ptr p(bml::make_unique_definit()); BOOST_TEST(0 == std::memcmp(p.get(), ff_patternbuf, sizeof(ff_patternbuf))); } + { + bml::unique_ptr p(bml::make_unique_nothrow_definit()); + BOOST_TEST(0 == std::memcmp(p.get(), dd_patternbuf, sizeof(dd_patternbuf))); + } + BOOST_TEST(A::count == 0); { bml::unique_ptr p(bml::make_unique()); @@ -88,7 +105,7 @@ void test() } BOOST_TEST(A::count == 0); { - bml::unique_ptr p(bml::make_unique(0)); + bml::unique_ptr p(bml::make_unique_nothrow(0)); BOOST_TEST(A::count == 1); BOOST_TEST(p->a == 0); BOOST_TEST(p->b == 1000); @@ -104,7 +121,7 @@ void test() } BOOST_TEST(A::count == 0); { - bml::unique_ptr p(bml::make_unique(0, 1, 2)); + bml::unique_ptr p(bml::make_unique_nothrow(0, 1, 2)); BOOST_TEST(A::count == 1); BOOST_TEST(p->a == 0); BOOST_TEST(p->b == 1); @@ -115,6 +132,7 @@ void test() } //namespace make_unique_single{ + //////////////////////////////// // make_unique_single //////////////////////////////// @@ -135,6 +153,16 @@ void test() } } BOOST_TEST(A::count == 0); + { + bml::unique_ptr p(bml::make_unique_nothrow(10)); + BOOST_TEST(A::count == 10); + for(int i = 0; i != 10; ++i){ + BOOST_TEST(p[i].a == 999); + BOOST_TEST(p[i].b == 1000); + BOOST_TEST(p[i].c == 1001); + } + } + BOOST_TEST(A::count == 0); reset_counters(); { bml::unique_ptr p(bml::make_unique_definit(10)); @@ -142,6 +170,13 @@ void test() BOOST_TEST(0 == std::memcmp(&p[i], ee_patternbuf, sizeof(ee_patternbuf))); } } + reset_counters(); + { + bml::unique_ptr p(bml::make_unique_nothrow_definit(10)); + for(unsigned i = 0; i != 10; ++i){ + BOOST_TEST(0 == std::memcmp(&p[i], cc_patternbuf, sizeof(cc_patternbuf))); + } + } } } //namespace make_unique_array{