From a41b81f1c8dde941a14835c5eebe3aaa869ca714 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 12 Dec 2013 01:22:51 +0200 Subject: [PATCH 01/39] Added shared_array constructor from nullptr, per #8894. --- include/boost/smart_ptr/shared_array.hpp | 8 ++ test/Jamfile.v2 | 3 +- test/sa_nullptr_test.cpp | 112 +++++++++++++++++++++++ 3 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 test/sa_nullptr_test.cpp diff --git a/include/boost/smart_ptr/shared_array.hpp b/include/boost/smart_ptr/shared_array.hpp index 73a07ae..2bb2852 100644 --- a/include/boost/smart_ptr/shared_array.hpp +++ b/include/boost/smart_ptr/shared_array.hpp @@ -61,6 +61,14 @@ public: { } +#if !defined( BOOST_NO_CXX11_NULLPTR ) + + shared_array( boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT : px( 0 ), pn() + { + } + +#endif + template explicit shared_array( Y * p ): px( p ), pn( p, checked_array_deleter() ) { diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 874968a..f90316e 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -1,6 +1,6 @@ # Boost.SmartPtr Library test Jamfile # -# Copyright (c) 2003-2007 Peter Dimov +# Copyright (c) 2003-2013 Peter Dimov # Copyright (c) 2003 Dave Abrahams # # Distributed under the Boost Software License, Version 1.0. (See @@ -78,6 +78,7 @@ import testing ; [ run sp_array_cast_test.cpp ] [ run sp_zero_compare_test.cpp ] [ run sp_nullptr_test.cpp ] + [ run sa_nullptr_test.cpp ] [ compile-fail array_fail_spa_sp_c.cpp ] [ compile-fail array_fail_sp_spa_c.cpp ] diff --git a/test/sa_nullptr_test.cpp b/test/sa_nullptr_test.cpp new file mode 100644 index 0000000..a051d32 --- /dev/null +++ b/test/sa_nullptr_test.cpp @@ -0,0 +1,112 @@ +// +// shared_array nullptr test +// +// Copyright 2012, 2013 Peter Dimov +// +// 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 +// + +#include +#include +#include +#include + +#if !defined( BOOST_NO_CXX11_NULLPTR ) + +struct X +{ + static int instances; + + X() + { + ++instances; + } + + ~X() + { + --instances; + } + +private: + + X( X const & ); + X & operator=( X const & ); +}; + +int X::instances = 0; + +int main() +{ + { + boost::shared_array p( nullptr ); + + BOOST_TEST( p.get() == 0 ); + BOOST_TEST( p.use_count() == 0 ); + + BOOST_TEST( p == nullptr ); + BOOST_TEST( nullptr == p ); + BOOST_TEST( !( p != nullptr ) ); + BOOST_TEST( !( nullptr != p ) ); + } + + { + boost::shared_array p( new int[ 1 ] ); + + BOOST_TEST( p.get() != 0 ); + BOOST_TEST( p.use_count() == 1 ); + + BOOST_TEST( p != nullptr ); + BOOST_TEST( nullptr != p ); + BOOST_TEST( !( p == nullptr ) ); + BOOST_TEST( !( nullptr == p ) ); + + p = nullptr; + + BOOST_TEST( p.get() == 0 ); + BOOST_TEST( p.use_count() == 0 ); + + BOOST_TEST( p == nullptr ); + BOOST_TEST( nullptr == p ); + BOOST_TEST( !( p != nullptr ) ); + BOOST_TEST( !( nullptr != p ) ); + } + + { + BOOST_TEST( X::instances == 0 ); + + boost::shared_array p( new X[ 2 ] ); + BOOST_TEST( X::instances == 2 ); + + BOOST_TEST( p.get() != 0 ); + BOOST_TEST( p.use_count() == 1 ); + + BOOST_TEST( p != nullptr ); + BOOST_TEST( nullptr != p ); + BOOST_TEST( !( p == nullptr ) ); + BOOST_TEST( !( nullptr == p ) ); + + p = nullptr; + BOOST_TEST( X::instances == 0 ); + + BOOST_TEST( p.get() == 0 ); + BOOST_TEST( p.use_count() == 0 ); + + BOOST_TEST( p == nullptr ); + BOOST_TEST( nullptr == p ); + BOOST_TEST( !( p != nullptr ) ); + BOOST_TEST( !( nullptr != p ) ); + } + + return boost::report_errors(); +} + +#else + +int main() +{ + return 0; +} + +#endif From 4c8a55898239048a72dbfc1f936c7a4b19469041 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 12 Dec 2013 01:42:16 +0200 Subject: [PATCH 02/39] Check return values of pthread_* calls with BOOST_VERIFY, per #8904. --- include/boost/smart_ptr/detail/atomic_count_pthreads.hpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/include/boost/smart_ptr/detail/atomic_count_pthreads.hpp b/include/boost/smart_ptr/detail/atomic_count_pthreads.hpp index 05f7867..f99b910 100644 --- a/include/boost/smart_ptr/detail/atomic_count_pthreads.hpp +++ b/include/boost/smart_ptr/detail/atomic_count_pthreads.hpp @@ -11,6 +11,7 @@ // http://www.boost.org/LICENSE_1_0.txt) // +#include #include // @@ -37,12 +38,12 @@ private: scoped_lock(pthread_mutex_t & m): m_(m) { - pthread_mutex_lock(&m_); + BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 ); } ~scoped_lock() { - pthread_mutex_unlock(&m_); + BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 ); } private: @@ -54,12 +55,12 @@ public: explicit atomic_count(long v): value_(v) { - pthread_mutex_init(&mutex_, 0); + BOOST_VERIFY( pthread_mutex_init( &mutex_, 0 ) == 0 ); } ~atomic_count() { - pthread_mutex_destroy(&mutex_); + BOOST_VERIFY( pthread_mutex_destroy( &mutex_ ) == 0 ); } long operator++() From bba3b446bdfaf44cfe20c9c6826f12b2843ab174 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 12 Dec 2013 02:36:33 +0200 Subject: [PATCH 03/39] Check return values of pthread_* calls with BOOST_VERIFY, per #8898 --- .../smart_ptr/detail/sp_counted_base_pt.hpp | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/include/boost/smart_ptr/detail/sp_counted_base_pt.hpp b/include/boost/smart_ptr/detail/sp_counted_base_pt.hpp index a742c3d..a16d2d8 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base_pt.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base_pt.hpp @@ -19,6 +19,7 @@ // #include +#include #include namespace boost @@ -46,15 +47,15 @@ public: // HPUX 10.20 / DCE has a nonstandard pthread_mutex_init #if defined(__hpux) && defined(_DECTHREADS_) - pthread_mutex_init( &m_, pthread_mutexattr_default ); + BOOST_VERIFY( pthread_mutex_init( &m_, pthread_mutexattr_default ) == 0 ); #else - pthread_mutex_init( &m_, 0 ); + BOOST_VERIFY( pthread_mutex_init( &m_, 0 ) == 0 ); #endif } virtual ~sp_counted_base() // nothrow { - pthread_mutex_destroy( &m_ ); + BOOST_VERIFY( pthread_mutex_destroy( &m_ ) == 0 ); } // dispose() is called when use_count_ drops to zero, to release @@ -74,24 +75,24 @@ public: void add_ref_copy() { - pthread_mutex_lock( &m_ ); + BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 ); ++use_count_; - pthread_mutex_unlock( &m_ ); + BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 ); } bool add_ref_lock() // true on success { - pthread_mutex_lock( &m_ ); + BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 ); bool r = use_count_ == 0? false: ( ++use_count_, true ); - pthread_mutex_unlock( &m_ ); + BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 ); return r; } void release() // nothrow { - pthread_mutex_lock( &m_ ); + BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 ); long new_use_count = --use_count_; - pthread_mutex_unlock( &m_ ); + BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 ); if( new_use_count == 0 ) { @@ -102,16 +103,16 @@ public: void weak_add_ref() // nothrow { - pthread_mutex_lock( &m_ ); + BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 ); ++weak_count_; - pthread_mutex_unlock( &m_ ); + BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 ); } void weak_release() // nothrow { - pthread_mutex_lock( &m_ ); + BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 ); long new_weak_count = --weak_count_; - pthread_mutex_unlock( &m_ ); + BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 ); if( new_weak_count == 0 ) { @@ -121,9 +122,9 @@ public: long use_count() const // nothrow { - pthread_mutex_lock( &m_ ); + BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 ); long r = use_count_; - pthread_mutex_unlock( &m_ ); + BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 ); return r; } From fed15ad8c50921cbfc0365156e4e4f4454dc1b91 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 13 Dec 2013 22:58:09 +0200 Subject: [PATCH 04/39] Add support for BOOST_SP_USE_STD_ATOMIC --- .../smart_ptr/detail/sp_counted_base.hpp | 5 +- .../detail/sp_counted_base_std_atomic.hpp | 137 ++++++++++++++++++ 2 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 include/boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp diff --git a/include/boost/smart_ptr/detail/sp_counted_base.hpp b/include/boost/smart_ptr/detail/sp_counted_base.hpp index 9ced2b9..c415892 100644 --- a/include/boost/smart_ptr/detail/sp_counted_base.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_base.hpp @@ -10,7 +10,7 @@ // // detail/sp_counted_base.hpp // -// Copyright 2005, 2006 Peter Dimov +// Copyright 2005-2013 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -23,6 +23,9 @@ #if defined( BOOST_SP_DISABLE_THREADS ) # include +#elif defined( BOOST_SP_USE_STD_ATOMIC ) +# include + #elif defined( BOOST_SP_USE_SPINLOCK ) # include diff --git a/include/boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp b/include/boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp new file mode 100644 index 0000000..cab8453 --- /dev/null +++ b/include/boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp @@ -0,0 +1,137 @@ +#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_STD_ATOMIC_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_STD_ATOMIC_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// detail/sp_counted_base_std_atomic.hpp - C++11 std::atomic +// +// Copyright (c) 2007, 2013 Peter Dimov +// +// 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 + +#include +#include +#include + +namespace boost +{ + +namespace detail +{ + +inline void atomic_increment( std::atomic_int_least32_t * pw ) +{ + pw->fetch_add( 1, std::memory_order_relaxed ); +} + +inline std::int_least32_t atomic_decrement( std::atomic_int_least32_t * pw ) +{ + return pw->fetch_sub( 1, std::memory_order_acq_rel ); +} + +inline std::int_least32_t atomic_conditional_increment( std::atomic_int_least32_t * pw ) +{ + // long r = *pw; + // if( r != 0 ) ++*pw; + // return r; + + std::int_least32_t r = pw->load( std::memory_order_relaxed ); + + for( ;; ) + { + if( r == 0 ) + { + return r; + } + + if( pw->compare_exchange_weak( r, r + 1, std::memory_order_relaxed, std::memory_order_relaxed ) ) + { + return r; + } + } +} + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + std::atomic_int_least32_t use_count_; // #shared + std::atomic_int_least32_t weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_untyped_deleter() = 0; + + void add_ref_copy() + { + atomic_increment( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + return atomic_conditional_increment( &use_count_ ) != 0; + } + + void release() // nothrow + { + if( atomic_decrement( &use_count_ ) == 1 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_increment( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_decrement( &weak_count_ ) == 1 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return use_count_.load( std::memory_order_acquire ); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_STD_ATOMIC_HPP_INCLUDED From 6e0ee3054330bad7701c5fa942f5e41440c0ffff Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 14 Dec 2013 00:01:01 +0200 Subject: [PATCH 05/39] Update atomic_count.hpp to match sp_counted_base.hpp. --- .../boost/smart_ptr/detail/atomic_count.hpp | 95 +++++++------------ .../smart_ptr/detail/atomic_count_nt.hpp | 59 ++++++++++++ ...count_pthreads.hpp => atomic_count_pt.hpp} | 0 .../smart_ptr/detail/atomic_count_spin.hpp | 62 ++++++++++++ .../detail/atomic_count_std_atomic.hpp | 60 ++++++++++++ 5 files changed, 217 insertions(+), 59 deletions(-) create mode 100644 include/boost/smart_ptr/detail/atomic_count_nt.hpp rename include/boost/smart_ptr/detail/{atomic_count_pthreads.hpp => atomic_count_pt.hpp} (100%) create mode 100644 include/boost/smart_ptr/detail/atomic_count_spin.hpp create mode 100644 include/boost/smart_ptr/detail/atomic_count_std_atomic.hpp diff --git a/include/boost/smart_ptr/detail/atomic_count.hpp b/include/boost/smart_ptr/detail/atomic_count.hpp index cc44ac2..8aefd44 100644 --- a/include/boost/smart_ptr/detail/atomic_count.hpp +++ b/include/boost/smart_ptr/detail/atomic_count.hpp @@ -11,10 +11,11 @@ // boost/detail/atomic_count.hpp - thread/SMP safe reference counter // // Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. +// Copyright (c) 2013 Peter Dimov // -// 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) +// 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 // // typedef boost::detail::atomic_count; // @@ -27,92 +28,68 @@ // a; // // Returns: (long) the current value of a +// Memory Ordering: acquire // // ++a; // // Effects: Atomically increments the value of a // Returns: (long) the new value of a +// Memory Ordering: acquire/release // // --a; // // Effects: Atomically decrements the value of a // Returns: (long) the new value of a -// -// Important note: when --a returns zero, it must act as a -// read memory barrier (RMB); i.e. the calling thread must -// have a synchronized view of the memory -// -// On Intel IA-32 (x86) memory is always synchronized, so this -// is not a problem. -// -// On many architectures the atomic instructions already act as -// a memory barrier. -// -// This property is necessary for proper reference counting, since -// a thread can update the contents of a shared object, then -// release its reference, and another thread may immediately -// release the last reference causing object destruction. -// -// The destructor needs to have a synchronized view of the -// object to perform proper cleanup. -// -// Original example by Alexander Terekhov: -// -// Given: -// -// - a mutable shared object OBJ; -// - two threads THREAD1 and THREAD2 each holding -// a private smart_ptr object pointing to that OBJ. -// -// t1: THREAD1 updates OBJ (thread-safe via some synchronization) -// and a few cycles later (after "unlock") destroys smart_ptr; -// -// t2: THREAD2 destroys smart_ptr WITHOUT doing any synchronization -// with respect to shared mutable object OBJ; OBJ destructors -// are called driven by smart_ptr interface... +// Memory Ordering: acquire/release // #include #include -#ifndef BOOST_HAS_THREADS +#if defined( BOOST_AC_DISABLE_THREADS ) +# include -namespace boost -{ +#elif defined( BOOST_AC_USE_STD_ATOMIC ) +# include -namespace detail -{ +#elif defined( BOOST_AC_USE_SPINLOCK ) +# include -typedef long atomic_count; +#elif defined( BOOST_AC_USE_PTHREADS ) +# include -} +#elif defined( BOOST_SP_DISABLE_THREADS ) +# include -} +#elif defined( BOOST_SP_USE_STD_ATOMIC ) +# include -#elif defined(BOOST_AC_USE_PTHREADS) -# include +#elif defined( BOOST_SP_USE_SPINLOCK ) +# include -#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) -# include +#elif defined( BOOST_SP_USE_PTHREADS ) +# include -#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) -# include +#elif defined( BOOST_DISABLE_THREADS ) && !defined( BOOST_SP_ENABLE_THREADS ) && !defined( BOOST_DISABLE_WIN32 ) +# include + +#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) && !defined( __PATHSCALE__ ) +# include #elif defined( BOOST_SP_HAS_SYNC ) -# include +# include + +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# include #elif defined(__GLIBCPP__) || defined(__GLIBCXX__) -# include +# include -#elif defined(BOOST_HAS_PTHREADS) - -# define BOOST_AC_USE_PTHREADS -# include +#elif !defined( BOOST_HAS_THREADS ) +# include #else - -// Use #define BOOST_DISABLE_THREADS to avoid the error -#error Unrecognized threading platform +# include #endif diff --git a/include/boost/smart_ptr/detail/atomic_count_nt.hpp b/include/boost/smart_ptr/detail/atomic_count_nt.hpp new file mode 100644 index 0000000..3bbf138 --- /dev/null +++ b/include/boost/smart_ptr/detail/atomic_count_nt.hpp @@ -0,0 +1,59 @@ +#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_NT_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_NT_HPP_INCLUDED + +// +// boost/detail/atomic_count_nt.hpp +// +// Trivial atomic_count for the single-threaded case +// +// http://gcc.gnu.org/onlinedocs/porting/Thread-safety.html +// +// Copyright 2013 Peter Dimov +// +// 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 +// + +namespace boost +{ + +namespace detail +{ + +class atomic_count +{ +public: + + explicit atomic_count( long v ): value_( v ) + { + } + + long operator++() + { + return ++value_; + } + + long operator--() + { + return --value_; + } + + operator long() const + { + return value_; + } + +private: + + atomic_count(atomic_count const &); + atomic_count & operator=(atomic_count const &); + + long value_; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_NT_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/atomic_count_pthreads.hpp b/include/boost/smart_ptr/detail/atomic_count_pt.hpp similarity index 100% rename from include/boost/smart_ptr/detail/atomic_count_pthreads.hpp rename to include/boost/smart_ptr/detail/atomic_count_pt.hpp diff --git a/include/boost/smart_ptr/detail/atomic_count_spin.hpp b/include/boost/smart_ptr/detail/atomic_count_spin.hpp new file mode 100644 index 0000000..8e62349 --- /dev/null +++ b/include/boost/smart_ptr/detail/atomic_count_spin.hpp @@ -0,0 +1,62 @@ +#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SPIN_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SPIN_HPP_INCLUDED + +// +// boost/detail/atomic_count_spin.hpp +// +// Copyright (c) 2013 Peter Dimov +// +// 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 +// + +#include + +namespace boost +{ + +namespace detail +{ + +class atomic_count +{ +private: + +public: + + explicit atomic_count( long v ): value_( v ) + { + } + + long operator++() + { + spinlock_pool<0>::scoped_lock lock( &value_ ); + return ++value_; + } + + long operator--() + { + spinlock_pool<0>::scoped_lock lock( &value_ ); + return --value_; + } + + operator long() const + { + spinlock_pool<0>::scoped_lock lock( &value_ ); + return value_; + } + +private: + + atomic_count(atomic_count const &); + atomic_count & operator=(atomic_count const &); + + long value_; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SPIN_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/atomic_count_std_atomic.hpp b/include/boost/smart_ptr/detail/atomic_count_std_atomic.hpp new file mode 100644 index 0000000..55b9998 --- /dev/null +++ b/include/boost/smart_ptr/detail/atomic_count_std_atomic.hpp @@ -0,0 +1,60 @@ +#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_STD_ATOMIC_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_STD_ATOMIC_HPP_INCLUDED + +// +// boost/detail/atomic_count_std_atomic.hpp +// +// atomic_count for std::atomic +// +// Copyright 2013 Peter Dimov +// +// 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 +// + +#include +#include + +namespace boost +{ + +namespace detail +{ + +class atomic_count +{ +public: + + explicit atomic_count( long v ): value_( v ) + { + } + + long operator++() + { + return value_.fetch_add( 1, std::memory_order_acq_rel ) + 1; + } + + long operator--() + { + return value_.fetch_sub( 1, std::memory_order_acq_rel ) - 1; + } + + operator long() const + { + return value_.load( std::memory_order_acquire ); + } + +private: + + atomic_count(atomic_count const &); + atomic_count & operator=(atomic_count const &); + + std::atomic_int_least32_t value_; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_STD_ATOMIC_HPP_INCLUDED From d7fa365843f5682338d5b4a47d33341a6a25a797 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 14 Dec 2013 00:15:51 +0200 Subject: [PATCH 06/39] Remove obsolete _nmt headers. --- .../smart_ptr/detail/shared_array_nmt.hpp | 151 --------------- .../boost/smart_ptr/detail/shared_ptr_nmt.hpp | 182 ------------------ include/boost/smart_ptr/shared_array.hpp | 6 - include/boost/smart_ptr/shared_ptr.hpp | 6 - 4 files changed, 345 deletions(-) delete mode 100644 include/boost/smart_ptr/detail/shared_array_nmt.hpp delete mode 100644 include/boost/smart_ptr/detail/shared_ptr_nmt.hpp diff --git a/include/boost/smart_ptr/detail/shared_array_nmt.hpp b/include/boost/smart_ptr/detail/shared_array_nmt.hpp deleted file mode 100644 index 450c9bc..0000000 --- a/include/boost/smart_ptr/detail/shared_array_nmt.hpp +++ /dev/null @@ -1,151 +0,0 @@ -#ifndef BOOST_SMART_PTR_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED -#define BOOST_SMART_PTR_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED - -// -// detail/shared_array_nmt.hpp - shared_array.hpp without member templates -// -// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. -// Copyright (c) 2001, 2002 Peter Dimov -// -// 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/smart_ptr/shared_array.htm for documentation. -// - -#include -#include -#include -#include - -#include // for std::ptrdiff_t -#include // for std::swap -#include // for std::less -#include // for std::bad_alloc - -namespace boost -{ - -template class shared_array -{ -private: - - typedef detail::atomic_count count_type; - -public: - - typedef T element_type; - - explicit shared_array(T * p = 0): px(p) - { -#ifndef BOOST_NO_EXCEPTIONS - - try // prevent leak if new throws - { - pn = new count_type(1); - } - catch(...) - { - boost::checked_array_delete(p); - throw; - } - -#else - - pn = new count_type(1); - - if(pn == 0) - { - boost::checked_array_delete(p); - boost::throw_exception(std::bad_alloc()); - } - -#endif - } - - ~shared_array() - { - if(--*pn == 0) - { - boost::checked_array_delete(px); - delete pn; - } - } - - shared_array(shared_array const & r) : px(r.px) // never throws - { - pn = r.pn; - ++*pn; - } - - shared_array & operator=(shared_array const & r) - { - shared_array(r).swap(*this); - return *this; - } - - void reset(T * p = 0) - { - BOOST_ASSERT(p == 0 || p != px); - shared_array(p).swap(*this); - } - - T * get() const // never throws - { - return px; - } - - T & operator[](std::ptrdiff_t i) const // never throws - { - BOOST_ASSERT(px != 0); - BOOST_ASSERT(i >= 0); - return px[i]; - } - - long use_count() const // never throws - { - return *pn; - } - - bool unique() const // never throws - { - return *pn == 1; - } - - void swap(shared_array & other) // never throws - { - std::swap(px, other.px); - std::swap(pn, other.pn); - } - -private: - - T * px; // contained pointer - count_type * pn; // ptr to reference counter - -}; // shared_array - -template inline bool operator==(shared_array const & a, shared_array const & b) -{ - return a.get() == b.get(); -} - -template inline bool operator!=(shared_array const & a, shared_array const & b) -{ - return a.get() != b.get(); -} - -template inline bool operator<(shared_array const & a, shared_array const & b) -{ - return std::less()(a.get(), b.get()); -} - -template void swap(shared_array & a, shared_array & b) -{ - a.swap(b); -} - -} // namespace boost - -#endif // #ifndef BOOST_SMART_PTR_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/shared_ptr_nmt.hpp b/include/boost/smart_ptr/detail/shared_ptr_nmt.hpp deleted file mode 100644 index afc1ec0..0000000 --- a/include/boost/smart_ptr/detail/shared_ptr_nmt.hpp +++ /dev/null @@ -1,182 +0,0 @@ -#ifndef BOOST_SMART_PTR_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED -#define BOOST_SMART_PTR_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED - -// -// detail/shared_ptr_nmt.hpp - shared_ptr.hpp without member templates -// -// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. -// Copyright (c) 2001, 2002 Peter Dimov -// -// 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/smart_ptr/shared_ptr.htm for documentation. -// - -#include -#include -#include -#include - -#ifndef BOOST_NO_AUTO_PTR -# include // for std::auto_ptr -#endif - -#include // for std::swap -#include // for std::less -#include // for std::bad_alloc - -namespace boost -{ - -template class shared_ptr -{ -private: - - typedef detail::atomic_count count_type; - -public: - - typedef T element_type; - typedef T value_type; - - explicit shared_ptr(T * p = 0): px(p) - { -#ifndef BOOST_NO_EXCEPTIONS - - try // prevent leak if new throws - { - pn = new count_type(1); - } - catch(...) - { - boost::checked_delete(p); - throw; - } - -#else - - pn = new count_type(1); - - if(pn == 0) - { - boost::checked_delete(p); - boost::throw_exception(std::bad_alloc()); - } - -#endif - } - - ~shared_ptr() - { - if(--*pn == 0) - { - boost::checked_delete(px); - delete pn; - } - } - - shared_ptr(shared_ptr const & r): px(r.px) // never throws - { - pn = r.pn; - ++*pn; - } - - shared_ptr & operator=(shared_ptr const & r) - { - shared_ptr(r).swap(*this); - return *this; - } - -#ifndef BOOST_NO_AUTO_PTR - - explicit shared_ptr(std::auto_ptr & r) - { - pn = new count_type(1); // may throw - px = r.release(); // fix: moved here to stop leak if new throws - } - - shared_ptr & operator=(std::auto_ptr & r) - { - shared_ptr(r).swap(*this); - return *this; - } - -#endif - - void reset(T * p = 0) - { - BOOST_ASSERT(p == 0 || p != px); - shared_ptr(p).swap(*this); - } - - T & operator*() const // never throws - { - BOOST_ASSERT(px != 0); - return *px; - } - - T * operator->() const // never throws - { - BOOST_ASSERT(px != 0); - return px; - } - - T * get() const // never throws - { - return px; - } - - long use_count() const // never throws - { - return *pn; - } - - bool unique() const // never throws - { - return *pn == 1; - } - - void swap(shared_ptr & other) // never throws - { - std::swap(px, other.px); - std::swap(pn, other.pn); - } - -private: - - T * px; // contained pointer - count_type * pn; // ptr to reference counter -}; - -template inline bool operator==(shared_ptr const & a, shared_ptr const & b) -{ - return a.get() == b.get(); -} - -template inline bool operator!=(shared_ptr const & a, shared_ptr const & b) -{ - return a.get() != b.get(); -} - -template inline bool operator<(shared_ptr const & a, shared_ptr const & b) -{ - return std::less()(a.get(), b.get()); -} - -template void swap(shared_ptr & a, shared_ptr & b) -{ - a.swap(b); -} - -// get_pointer() enables boost::mem_fn to recognize shared_ptr - -template inline T * get_pointer(shared_ptr const & p) -{ - return p.get(); -} - -} // namespace boost - -#endif // #ifndef BOOST_SMART_PTR_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED diff --git a/include/boost/smart_ptr/shared_array.hpp b/include/boost/smart_ptr/shared_array.hpp index 2bb2852..fd58071 100644 --- a/include/boost/smart_ptr/shared_array.hpp +++ b/include/boost/smart_ptr/shared_array.hpp @@ -16,10 +16,6 @@ #include // for broken compiler workarounds -#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) -#include -#else - #include // TR1 cyclic inclusion fix #include @@ -293,6 +289,4 @@ template< class D, class T > D * get_deleter( shared_array const & p ) } // namespace boost -#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) - #endif // #ifndef BOOST_SMART_PTR_SHARED_ARRAY_HPP_INCLUDED diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp index 9259ca0..3aeb489 100644 --- a/include/boost/smart_ptr/shared_ptr.hpp +++ b/include/boost/smart_ptr/shared_ptr.hpp @@ -16,10 +16,6 @@ #include // for broken compiler workarounds -#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) -#include -#else - // In order to avoid circular dependencies with Boost.TR1 // we make sure that our include of doesn't try to // pull in the TR1 headers: that's why we use this header @@ -1030,6 +1026,4 @@ template< class T > std::size_t hash_value( boost::shared_ptr const & p ) BOO } // namespace boost -#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) - #endif // #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED From 73153d57971849d6cfd13e2bd1bf2b0c9894797d Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Mon, 2 Dec 2013 12:30:20 +0200 Subject: [PATCH 07/39] Add intrusive_ptr<>::detach() This provides a way to escape from automatic reference counting, and taking manual control of the reference. Useful when interfacing to a C API that expects a pointer with an elevated reference count. Similar to std::unique_ptr<>::release(). --- include/boost/smart_ptr/intrusive_ptr.hpp | 7 +++++++ intrusive_ptr.html | 17 +++++++++++++++++ test/intrusive_ptr_test.cpp | 7 +++++++ 3 files changed, 31 insertions(+) diff --git a/include/boost/smart_ptr/intrusive_ptr.hpp b/include/boost/smart_ptr/intrusive_ptr.hpp index b6f5bcd..42fdd92 100644 --- a/include/boost/smart_ptr/intrusive_ptr.hpp +++ b/include/boost/smart_ptr/intrusive_ptr.hpp @@ -151,6 +151,13 @@ public: return px; } + T * detach() BOOST_NOEXCEPT + { + T * ret = px; + px = 0; + return ret; + } + T & operator*() const { BOOST_ASSERT( px != 0 ); diff --git a/intrusive_ptr.html b/intrusive_ptr.html index 562d27a..7028444 100644 --- a/intrusive_ptr.html +++ b/intrusive_ptr.html @@ -71,6 +71,7 @@ T & operator*() const; // never throws T * operator->() const; // never throws T * get() const; // never throws + T * detach(); // never throws operator unspecified-bool-type() const; // never throws @@ -179,6 +180,22 @@ intrusive_ptr & operator=(T * r);

Returns: the stored pointer.

Throws: nothing.

+

detach

+
T * detach(); // never throws
+
+

Returns: the stored pointer.

+

Throws: nothing.

+

Postconditions: get() == 0.

+

Notes: The returned pointer has an elevated reference count. This + allows conversion of an intrusive_ptr back to a raw pointer, + without the performance overhead of acquiring and dropping an extra + reference. It can be viewed as the complement of the + non-reference-incrementing constructor.

+

Caution: Using detach escapes the safety of automatic + reference counting provided by intrusive_ptr. It should + by used only where strictly necessary (such as when interfacing to an + existing API), and when the implications are thoroughly understood.

+

conversions

operator unspecified-bool-type () const; // never throws
diff --git a/test/intrusive_ptr_test.cpp b/test/intrusive_ptr_test.cpp index 614a9cb..f53d75d 100644 --- a/test/intrusive_ptr_test.cpp +++ b/test/intrusive_ptr_test.cpp @@ -330,6 +330,13 @@ void test() BOOST_TEST(get_pointer(px) == px.get()); } + + { + boost::intrusive_ptr px(new X); + X* detached = px.detach(); + BOOST_TEST(detached->use_count() == 1); + delete detached; + } } } // namespace n_access From 4e46cb060931559258f0e0d949044838857e5e92 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 26 Dec 2013 18:05:52 +0200 Subject: [PATCH 08/39] Add one more intrusive_ptr test case. --- test/intrusive_ptr_test.cpp | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/test/intrusive_ptr_test.cpp b/test/intrusive_ptr_test.cpp index f53d75d..b3f50fb 100644 --- a/test/intrusive_ptr_test.cpp +++ b/test/intrusive_ptr_test.cpp @@ -332,9 +332,26 @@ void test() } { - boost::intrusive_ptr px(new X); + boost::intrusive_ptr px; X* detached = px.detach(); - BOOST_TEST(detached->use_count() == 1); + BOOST_TEST( px.get() == 0 ); + BOOST_TEST( detached == 0 ); + } + + { + X * p = new X; + BOOST_TEST( p->use_count() == 0 ); + + boost::intrusive_ptr px( p ); + BOOST_TEST( px.get() == p ); + BOOST_TEST( px->use_count() == 1 ); + + X * detached = px.detach(); + BOOST_TEST( px.get() == 0 ); + + BOOST_TEST( detached == p ); + BOOST_TEST( detached->use_count() == 1 ); + delete detached; } } From 4de3f36839bfaf800e1f875d2f8e07412f9909bf Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 26 Dec 2013 18:47:05 +0200 Subject: [PATCH 09/39] Add add_ref parameter to intrusive_ptr::reset, add tests for reset. --- include/boost/smart_ptr/intrusive_ptr.hpp | 5 + intrusive_ptr.html | 9 +- test/intrusive_ptr_test.cpp | 217 +++++++++++++++++++++- 3 files changed, 221 insertions(+), 10 deletions(-) diff --git a/include/boost/smart_ptr/intrusive_ptr.hpp b/include/boost/smart_ptr/intrusive_ptr.hpp index 42fdd92..e5db609 100644 --- a/include/boost/smart_ptr/intrusive_ptr.hpp +++ b/include/boost/smart_ptr/intrusive_ptr.hpp @@ -146,6 +146,11 @@ public: this_type( rhs ).swap( *this ); } + void reset( T * rhs, bool add_ref ) + { + this_type( rhs, add_ref ).swap( *this ); + } + T * get() const BOOST_NOEXCEPT { return px; diff --git a/intrusive_ptr.html b/intrusive_ptr.html index 7028444..b7e884b 100644 --- a/intrusive_ptr.html +++ b/intrusive_ptr.html @@ -67,6 +67,7 @@ void reset(); void reset(T * r); + void reset(T * r, bool add_ref); T & operator*() const; // never throws T * operator->() const; // never throws @@ -161,6 +162,10 @@ intrusive_ptr & operator=(T * r);

Effects: Equivalent to intrusive_ptr(r).swap(*this).

+
void reset(T * r, bool add_ref);
+
+

Effects: Equivalent to intrusive_ptr(r, add_ref).swap(*this).

+

indirection

T & operator*() const; // never throws
@@ -307,9 +312,7 @@ intrusive_ptr & operator=(T * r);

- $Date$

-

- Copyright © 2003-2005 Peter Dimov. Distributed under the Boost Software License, Version + Copyright © 2003-2005, 2013 Peter Dimov. 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.

diff --git a/test/intrusive_ptr_test.cpp b/test/intrusive_ptr_test.cpp index b3f50fb..b46ddf3 100644 --- a/test/intrusive_ptr_test.cpp +++ b/test/intrusive_ptr_test.cpp @@ -51,14 +51,18 @@ protected: base(): use_count_(0) { + ++instances; } virtual ~base() { + --instances; } public: + static long instances; + long use_count() const { return use_count_; @@ -91,6 +95,8 @@ public: #endif }; +long base::instances = 0; + } // namespace N #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) @@ -161,19 +167,27 @@ void pointer_constructor() BOOST_TEST(px.get() == 0); } + BOOST_TEST( N::base::instances == 0 ); + { X * p = new X; BOOST_TEST(p->use_count() == 0); + BOOST_TEST( N::base::instances == 1 ); + boost::intrusive_ptr px(p); BOOST_TEST(px.get() == p); BOOST_TEST(px->use_count() == 1); } + BOOST_TEST( N::base::instances == 0 ); + { X * p = new X; BOOST_TEST(p->use_count() == 0); + BOOST_TEST( N::base::instances == 1 ); + #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) using boost::intrusive_ptr_add_ref; #endif @@ -184,6 +198,8 @@ void pointer_constructor() BOOST_TEST(px.get() == p); BOOST_TEST(px->use_count() == 1); } + + BOOST_TEST( N::base::instances == 0 ); } void copy_constructor() @@ -224,17 +240,27 @@ void copy_constructor() BOOST_TEST(px.get() == py.get()); } + BOOST_TEST( N::base::instances == 0 ); + { boost::intrusive_ptr px(new X); boost::intrusive_ptr px2(px); - BOOST_TEST(px2.get() == px.get()); + BOOST_TEST( px2.get() == px.get() ); + + BOOST_TEST( N::base::instances == 1 ); } + BOOST_TEST( N::base::instances == 0 ); + { boost::intrusive_ptr py(new Y); boost::intrusive_ptr px(py); - BOOST_TEST(px.get() == py.get()); + BOOST_TEST( px.get() == py.get() ); + + BOOST_TEST( N::base::instances == 1 ); } + + BOOST_TEST( N::base::instances == 0 ); } void test() @@ -251,15 +277,23 @@ namespace n_destructor void test() { - boost::intrusive_ptr px(new X); - BOOST_TEST(px->use_count() == 1); + BOOST_TEST( N::base::instances == 0 ); { - boost::intrusive_ptr px2(px); - BOOST_TEST(px->use_count() == 2); + boost::intrusive_ptr px(new X); + BOOST_TEST(px->use_count() == 1); + + BOOST_TEST( N::base::instances == 1 ); + + { + boost::intrusive_ptr px2(px); + BOOST_TEST(px->use_count() == 2); + } + + BOOST_TEST(px->use_count() == 1); } - BOOST_TEST(px->use_count() == 1); + BOOST_TEST( N::base::instances == 0 ); } } // namespace n_destructor @@ -288,6 +322,174 @@ void test() } // namespace n_assignment +namespace n_reset +{ + +void test() +{ + BOOST_TEST( N::base::instances == 0 ); + + { + boost::intrusive_ptr px; + BOOST_TEST( px.get() == 0 ); + + px.reset(); + BOOST_TEST( px.get() == 0 ); + + X * p = new X; + BOOST_TEST( p->use_count() == 0 ); + BOOST_TEST( N::base::instances == 1 ); + + px.reset( p ); + BOOST_TEST( px.get() == p ); + BOOST_TEST( px->use_count() == 1 ); + + px.reset(); + BOOST_TEST( px.get() == 0 ); + } + + BOOST_TEST( N::base::instances == 0 ); + + { + boost::intrusive_ptr px( new X ); + BOOST_TEST( N::base::instances == 1 ); + + px.reset( 0 ); + BOOST_TEST( px.get() == 0 ); + } + + BOOST_TEST( N::base::instances == 0 ); + + { + boost::intrusive_ptr px( new X ); + BOOST_TEST( N::base::instances == 1 ); + + px.reset( 0, false ); + BOOST_TEST( px.get() == 0 ); + } + + BOOST_TEST( N::base::instances == 0 ); + + { + boost::intrusive_ptr px( new X ); + BOOST_TEST( N::base::instances == 1 ); + + px.reset( 0, true ); + BOOST_TEST( px.get() == 0 ); + } + + BOOST_TEST( N::base::instances == 0 ); + + { + X * p = new X; + BOOST_TEST( p->use_count() == 0 ); + + BOOST_TEST( N::base::instances == 1 ); + + boost::intrusive_ptr px; + BOOST_TEST( px.get() == 0 ); + + px.reset( p, true ); + BOOST_TEST( px.get() == p ); + BOOST_TEST( px->use_count() == 1 ); + } + + BOOST_TEST( N::base::instances == 0 ); + + { + X * p = new X; + BOOST_TEST( p->use_count() == 0 ); + + BOOST_TEST( N::base::instances == 1 ); + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) + using boost::intrusive_ptr_add_ref; +#endif + intrusive_ptr_add_ref( p ); + BOOST_TEST( p->use_count() == 1 ); + + boost::intrusive_ptr px; + BOOST_TEST( px.get() == 0 ); + + px.reset( p, false ); + BOOST_TEST( px.get() == p ); + BOOST_TEST( px->use_count() == 1 ); + } + + BOOST_TEST( N::base::instances == 0 ); + + { + boost::intrusive_ptr px( new X ); + BOOST_TEST( px.get() != 0 ); + BOOST_TEST( px->use_count() == 1 ); + + BOOST_TEST( N::base::instances == 1 ); + + X * p = new X; + BOOST_TEST( p->use_count() == 0 ); + + BOOST_TEST( N::base::instances == 2 ); + + px.reset( p ); + BOOST_TEST( px.get() == p ); + BOOST_TEST( px->use_count() == 1 ); + + BOOST_TEST( N::base::instances == 1 ); + } + + BOOST_TEST( N::base::instances == 0 ); + + { + boost::intrusive_ptr px( new X ); + BOOST_TEST( px.get() != 0 ); + BOOST_TEST( px->use_count() == 1 ); + + BOOST_TEST( N::base::instances == 1 ); + + X * p = new X; + BOOST_TEST( p->use_count() == 0 ); + + BOOST_TEST( N::base::instances == 2 ); + + px.reset( p, true ); + BOOST_TEST( px.get() == p ); + BOOST_TEST( px->use_count() == 1 ); + + BOOST_TEST( N::base::instances == 1 ); + } + + BOOST_TEST( N::base::instances == 0 ); + + { + boost::intrusive_ptr px( new X ); + BOOST_TEST( px.get() != 0 ); + BOOST_TEST( px->use_count() == 1 ); + + BOOST_TEST( N::base::instances == 1 ); + + X * p = new X; + BOOST_TEST( p->use_count() == 0 ); + +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) + using boost::intrusive_ptr_add_ref; +#endif + intrusive_ptr_add_ref( p ); + BOOST_TEST( p->use_count() == 1 ); + + BOOST_TEST( N::base::instances == 2 ); + + px.reset( p, false ); + BOOST_TEST( px.get() == p ); + BOOST_TEST( px->use_count() == 1 ); + + BOOST_TEST( N::base::instances == 1 ); + } + + BOOST_TEST( N::base::instances == 0 ); +} + +} // namespace n_reset + namespace n_access { @@ -572,6 +774,7 @@ int main() n_constructors::test(); n_destructor::test(); n_assignment::test(); + n_reset::test(); n_access::test(); n_swap::test(); n_comparison::test(); From a68db557e82cc1ff3a4dacd52e72c1667575c832 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 26 Dec 2013 19:05:54 +0200 Subject: [PATCH 10/39] Deboldify, clean up intrusive_ptr.html. --- intrusive_ptr.html | 234 ++++++++++++++++++++++----------------------- 1 file changed, 117 insertions(+), 117 deletions(-) diff --git a/intrusive_ptr.html b/intrusive_ptr.html index b7e884b..d5d162f 100644 --- a/intrusive_ptr.html +++ b/intrusive_ptr.html @@ -2,48 +2,48 @@ intrusive_ptr - + - -

boost.png (6897 bytes)intrusive_ptr class template

+ +

boost.png (6897 bytes)intrusive_ptr class template

- Introduction
- Synopsis
- Members
- Free Functions
+ Introduction
+ Synopsis
+ Members
+ Free Functions

Introduction

-

The intrusive_ptr class template stores a pointer to an object with an - embedded reference count. Every new intrusive_ptr instance increments - the reference count by using an unqualified call to the function intrusive_ptr_add_ref, - passing it the pointer as an argument. Similarly, when an intrusive_ptr - is destroyed, it calls intrusive_ptr_release; this function is +

The intrusive_ptr class template stores a pointer to an object with an + embedded reference count. Every new intrusive_ptr instance increments + the reference count by using an unqualified call to the function intrusive_ptr_add_ref, + passing it the pointer as an argument. Similarly, when an intrusive_ptr + is destroyed, it calls intrusive_ptr_release; this function is responsible for destroying the object when its reference count drops to zero. The user is expected to provide suitable definitions of these two functions. On - compilers that support argument-dependent lookup, intrusive_ptr_add_ref - and intrusive_ptr_release should be defined in the namespace + compilers that support argument-dependent lookup, intrusive_ptr_add_ref + and intrusive_ptr_release should be defined in the namespace that corresponds to their parameter; otherwise, the definitions need to go in - namespace boost. The library provides a helper base class template - intrusive_ref_counter which may - help adding support for intrusive_ptr to user's types.

-

The class template is parameterized on T, the type of the object pointed - to. intrusive_ptr<T> can be implicitly converted to intrusive_ptr<U> - whenever T* can be implicitly converted to U*.

-

The main reasons to use intrusive_ptr are:

-
    -
  • + namespace boost. The library provides a helper base class template + intrusive_ref_counter which may + help adding support for intrusive_ptr to user types.

    +

    The class template is parameterized on T, the type of the object pointed + to. intrusive_ptr<T> can be implicitly converted to intrusive_ptr<U> + whenever T* can be implicitly converted to U*.

    +

    The main reasons to use intrusive_ptr are:

    +
      +
    • Some existing frameworks or OSes provide objects with embedded reference - counts; -
    • - The memory footprint of intrusive_ptr - is the same as the corresponding raw pointer; -
    • - intrusive_ptr<T> can be constructed from an arbitrary - raw pointer of type T *.
    -

    As a general rule, if it isn't obvious whether intrusive_ptr better - fits your needs than shared_ptr, try a shared_ptr-based - design first.

    + counts;
  • +
  • + The memory footprint of intrusive_ptr + is the same as the corresponding raw pointer;
  • +
  • + intrusive_ptr<T> can be constructed from an arbitrary + raw pointer of type T *.
+

As a general rule, if it isn't obvious whether intrusive_ptr better + fits your needs than shared_ptr, try a shared_ptr-based + design first.

Synopsis

namespace boost {
 
@@ -51,77 +51,77 @@
 
     public:
 
-      typedef T element_type;
+      typedef T element_type;
 
-      intrusive_ptr(); // never throws
-      intrusive_ptr(T * p, bool add_ref = true);
+      intrusive_ptr(); // never throws
+      intrusive_ptr(T * p, bool add_ref = true);
 
-      intrusive_ptr(intrusive_ptr const & r);
-      template<class Y> intrusive_ptr(intrusive_ptr<Y> const & r);
+      intrusive_ptr(intrusive_ptr const & r);
+      template<class Y> intrusive_ptr(intrusive_ptr<Y> const & r);
 
-      ~intrusive_ptr();
+      ~intrusive_ptr();
 
-      intrusive_ptr & operator=(intrusive_ptr const & r);
-      template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r);
-      intrusive_ptr & operator=(T * r);
+      intrusive_ptr & operator=(intrusive_ptr const & r);
+      template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r);
+      intrusive_ptr & operator=(T * r);
 
       void reset();
       void reset(T * r);
       void reset(T * r, bool add_ref);
 
-      T & operator*() const; // never throws
-      T * operator->() const; // never throws
-      T * get() const; // never throws
-      T * detach(); // never throws
+      T & operator*() const; // never throws
+      T * operator->() const; // never throws
+      T * get() const; // never throws
+      T * detach(); // never throws
 
-      operator unspecified-bool-type() const; // never throws
+      operator unspecified-bool-type() const; // never throws
 
-      void swap(intrusive_ptr & b); // never throws
+      void swap(intrusive_ptr & b); // never throws
   };
 
   template<class T, class U>
-    bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b); // never throws
+    bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b); // never throws
 
   template<class T, class U>
-    bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b); // never throws
+    bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b); // never throws
 
   template<class T>
-    bool operator==(intrusive_ptr<T> const & a, T * b); // never throws
+    bool operator==(intrusive_ptr<T> const & a, T * b); // never throws
 
   template<class T>
-    bool operator!=(intrusive_ptr<T> const & a, T * b); // never throws
+    bool operator!=(intrusive_ptr<T> const & a, T * b); // never throws
 
   template<class T>
-    bool operator==(T * a, intrusive_ptr<T> const & b); // never throws
+    bool operator==(T * a, intrusive_ptr<T> const & b); // never throws
 
   template<class T>
-    bool operator!=(T * a, intrusive_ptr<T> const & b); // never throws
+    bool operator!=(T * a, intrusive_ptr<T> const & b); // never throws
 
   template<class T, class U>
-    bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b); // never throws
+    bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b); // never throws
 
-  template<class T> void swap(intrusive_ptr<T> & a, intrusive_ptr<T> & b); // never throws
+  template<class T> void swap(intrusive_ptr<T> & a, intrusive_ptr<T> & b); // never throws
 
-  template<class T> T * get_pointer(intrusive_ptr<T> const & p); // never throws
+  template<class T> T * get_pointer(intrusive_ptr<T> const & p); // never throws
 
   template<class T, class U>
-    intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & r); // never throws
+    intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & r); // never throws
 
   template<class T, class U>
-    intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & r); // never throws
+    intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & r); // never throws
 
   template<class T, class U>
-    intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & r); // never throws
+    intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & r); // never throws
 
   template<class E, class T, class Y>
-    std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, intrusive_ptr<Y> const & p);
+    std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, intrusive_ptr<Y> const & p);
 
 }

Members

element_type

typedef T element_type;
-

Provides the type of the template parameter T.

+

Provides the type of the template parameter T.

constructors

intrusive_ptr(); // never throws
@@ -142,30 +142,30 @@ template<class Y> intrusive_ptr(intrusive_ptr<Y> const & r);

destructor

~intrusive_ptr();
-
-

Effects: if(get() != 0) intrusive_ptr_release(get());.

-
-

assignment

+
+

Effects: if(get() != 0) intrusive_ptr_release(get());.

+
+

assignment

intrusive_ptr & operator=(intrusive_ptr const & r);
 template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r);
 intrusive_ptr & operator=(T * r);
-
-

Effects: Equivalent to intrusive_ptr(r).swap(*this).

-

Returns: *this.

-
-

reset

+
+

Effects: Equivalent to intrusive_ptr(r).swap(*this).

+

Returns: *this.

+
+

reset

void reset();
-
-

Effects: Equivalent to intrusive_ptr().swap(*this).

-
+
+

Effects: Equivalent to intrusive_ptr().swap(*this).

+
void reset(T * r);
-
-

Effects: Equivalent to intrusive_ptr(r).swap(*this).

-
+
+

Effects: Equivalent to intrusive_ptr(r).swap(*this).

+
void reset(T * r, bool add_ref);
-
-

Effects: Equivalent to intrusive_ptr(r, add_ref).swap(*this).

-
+
+

Effects: Equivalent to intrusive_ptr(r, add_ref).swap(*this).

+

indirection

T & operator*() const; // never throws
@@ -192,7 +192,7 @@ intrusive_ptr & operator=(T * r);

Throws: nothing.

Postconditions: get() == 0.

Notes: The returned pointer has an elevated reference count. This - allows conversion of an intrusive_ptr back to a raw pointer, + allows conversion of an intrusive_ptr back to a raw pointer, without the performance overhead of acquiring and dropping an extra reference. It can be viewed as the complement of the non-reference-incrementing constructor.

@@ -207,10 +207,10 @@ intrusive_ptr & operator=(T * r);

Returns: an unspecified value that, when used in boolean contexts, is equivalent to get() != 0.

Throws: nothing.

-

Notes: This conversion operator allows intrusive_ptr objects to be +

Notes: This conversion operator allows intrusive_ptr objects to be used in boolean contexts, like if (p && p->valid()) {}. The actual target type is typically a pointer to a member function, avoiding - many of the implicit conversion pitfalls.

+ many of the implicit conversion pitfalls.

swap

void swap(intrusive_ptr & b); // never throws
@@ -261,59 +261,59 @@ intrusive_ptr & operator=(T * r);

Returns: std::less<T *>()(a.get(), b.get()).

Throws: nothing.

-

Notes: Allows intrusive_ptr objects to be used as keys - in associative containers.

+

Notes: Allows intrusive_ptr objects to be used as keys + in associative containers.

swap

template<class T>
   void swap(intrusive_ptr<T> & a, intrusive_ptr<T> & b); // never throws
-
-

Effects: Equivalent to a.swap(b).

-

Throws: nothing.

-

Notes: Matches the interface of std::swap. Provided as an aid to - generic programming.

-
+
+

Effects: Equivalent to a.swap(b).

+

Throws: nothing.

+

Notes: Matches the interface of std::swap. Provided as an aid to + generic programming.

+

get_pointer

template<class T>
   T * get_pointer(intrusive_ptr<T> const & p); // never throws
-
-

Returns: p.get().

-

Throws: nothing.

-

Notes: Provided as an aid to generic programming. Used by - mem_fn.

-
+
+

Returns: p.get().

+

Throws: nothing.

+

Notes: Provided as an aid to generic programming. Used by + mem_fn.

+

static_pointer_cast

template<class T, class U>
   intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & r); // never throws
-
-

Returns: intrusive_ptr<T>(static_cast<T*>(r.get())).

-

Throws: nothing.

-
+
+

Returns: intrusive_ptr<T>(static_cast<T*>(r.get())).

+

Throws: nothing.

+

const_pointer_cast

template<class T, class U>
   intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & r); // never throws
-
-

Returns: intrusive_ptr<T>(const_cast<T*>(r.get())).

-

Throws: nothing.

-
+
+

Returns: intrusive_ptr<T>(const_cast<T*>(r.get())).

+

Throws: nothing.

+

dynamic_pointer_cast

template<class T, class U>
   intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & r);
-
-

Returns: intrusive_ptr<T>(dynamic_cast<T*>(r.get())).

-

Throws: nothing.

-
+
+

Returns: intrusive_ptr<T>(dynamic_cast<T*>(r.get())).

+

Throws: nothing.

+

operator<<

template<class E, class T, class Y>
     std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, intrusive_ptr<Y> const & p);
-
-

Effects: os << p.get();.

-

Returns: os.

-
-
+
+

Effects: os << p.get();.

+

Returns: os.

+
+

Copyright © 2003-2005, 2013 Peter Dimov. 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.

+ 1.0. See accompanying file LICENSE_1_0.txt or + copy at http://www.boost.org/LICENSE_1_0.txt.

From 630e4f49f3df11c3e53426a47a894636fd763906 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Thu, 23 Jan 2014 20:40:46 -0800 Subject: [PATCH 11/39] Update make_shared for arrays to conform to N3870 Update make_shared and allocate_shared for arrays to be confined to the set of overloads specified in N3870. --- .../boost/smart_ptr/allocate_shared_array.hpp | 128 +--------- .../detail/allocate_array_helper.hpp | 35 ++- .../boost/smart_ptr/detail/array_deleter.hpp | 59 ++--- .../boost/smart_ptr/detail/array_traits.hpp | 9 +- .../boost/smart_ptr/detail/array_utility.hpp | 92 ++----- .../smart_ptr/detail/make_array_helper.hpp | 33 ++- .../boost/smart_ptr/detail/sp_if_array.hpp | 5 +- include/boost/smart_ptr/make_shared_array.hpp | 126 +--------- test/Jamfile.v2 | 18 +- test/allocate_shared_array_args_test.cpp | 173 ------------- test/allocate_shared_array_create_test.cpp | 114 --------- test/allocate_shared_array_esft_test.cpp | 7 +- test/allocate_shared_array_init_test.cpp | 84 ------- test/allocate_shared_array_noinit_test.cpp | 181 ++++++++++++++ test/allocate_shared_array_test.cpp | 236 +++++++++--------- test/allocate_shared_array_throws_test.cpp | 31 ++- test/allocate_shared_array_value_test.cpp | 46 ++++ test/allocate_shared_arrays_create_test.cpp | 94 ------- test/allocate_shared_arrays_init_test.cpp | 23 -- test/allocate_shared_arrays_test.cpp | 164 ++---------- test/make_shared_array_args_test.cpp | 172 ------------- test/make_shared_array_create_test.cpp | 114 --------- test/make_shared_array_esft_test.cpp | 7 +- test/make_shared_array_init_test.cpp | 84 ------- test/make_shared_array_noinit_test.cpp | 181 ++++++++++++++ test/make_shared_array_test.cpp | 230 +++++++++-------- test/make_shared_array_throws_test.cpp | 31 ++- test/make_shared_array_value_test.cpp | 46 ++++ test/make_shared_arrays_create_test.cpp | 94 ------- test/make_shared_arrays_init_test.cpp | 23 -- test/make_shared_arrays_test.cpp | 164 ++---------- 31 files changed, 963 insertions(+), 1841 deletions(-) delete mode 100644 test/allocate_shared_array_args_test.cpp delete mode 100644 test/allocate_shared_array_create_test.cpp delete mode 100644 test/allocate_shared_array_init_test.cpp create mode 100644 test/allocate_shared_array_noinit_test.cpp create mode 100644 test/allocate_shared_array_value_test.cpp delete mode 100644 test/allocate_shared_arrays_create_test.cpp delete mode 100644 test/allocate_shared_arrays_init_test.cpp delete mode 100644 test/make_shared_array_args_test.cpp delete mode 100644 test/make_shared_array_create_test.cpp delete mode 100644 test/make_shared_array_init_test.cpp create mode 100644 test/make_shared_array_noinit_test.cpp create mode 100644 test/make_shared_array_value_test.cpp delete mode 100644 test/make_shared_arrays_create_test.cpp delete mode 100644 test/make_shared_arrays_init_test.cpp diff --git a/include/boost/smart_ptr/allocate_shared_array.hpp b/include/boost/smart_ptr/allocate_shared_array.hpp index 3ee1655..b76e912 100644 --- a/include/boost/smart_ptr/allocate_shared_array.hpp +++ b/include/boost/smart_ptr/allocate_shared_array.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Glen Joseph Fernandes + * Copyright (c) 2012-2014 Glen Joseph Fernandes * glenfe at live dot com * * Distributed under the Boost Software License, @@ -14,9 +14,6 @@ #include #include #include -#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) -#include -#endif namespace boost { template @@ -36,67 +33,27 @@ namespace boost { d2->init(p2); return boost::shared_ptr(s1, p1); } -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - template - inline typename boost::detail::sp_if_array::type - allocate_shared(const A& allocator, std::size_t size, Args&&... args) { - typedef typename boost::detail::array_inner::type T1; - typedef typename boost::detail::array_base::type T2; - T1* p1 = 0; - T2* p2 = 0; - std::size_t n1 = size * boost::detail::array_total::size; - boost::detail::allocate_array_helper a1(allocator, n1, &p2); - boost::detail::array_deleter d1(n1); - boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; - p1 = reinterpret_cast(p2); - D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->init(p2, boost::detail::sp_forward(args)...); - return boost::shared_ptr(s1, p1); - } - template - inline typename boost::detail::sp_if_size_array::type - allocate_shared(const A& allocator, Args&&... args) { - typedef typename boost::detail::array_inner::type T1; - typedef typename boost::detail::array_base::type T2; - enum { - N = boost::detail::array_total::size - }; - T1* p1 = 0; - T2* p2 = 0; - boost::detail::allocate_array_helper a1(allocator, &p2); - boost::detail::array_deleter d1; - boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; - p1 = reinterpret_cast(p2); - D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->init(p2, boost::detail::sp_forward(args)...); - return boost::shared_ptr(s1, p1); - } -#endif -#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) + template inline typename boost::detail::sp_if_size_array::type - allocate_shared(const A& allocator, const T& list) { + allocate_shared(const A& allocator) { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; - typedef const T2 T3; enum { N = boost::detail::array_total::size }; T1* p1 = 0; T2* p2 = 0; - T3* p3 = 0; boost::detail::allocate_array_helper a1(allocator, &p2); boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); typedef boost::detail::array_deleter* D2; - p3 = reinterpret_cast(list); p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->init_list(p2, p3); + d2->init(p2); return boost::shared_ptr(s1, p1); } + template inline typename boost::detail::sp_if_array::type allocate_shared(const A& allocator, std::size_t size, @@ -115,12 +72,13 @@ namespace boost { boost::detail::array_deleter d1(n1); boost::shared_ptr s1(p1, d1, a1); typedef boost::detail::array_deleter* D2; - p3 = reinterpret_cast(list); + p3 = reinterpret_cast(&list); p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->template init_list(p2, p3); + d2->template init(p2, p3); return boost::shared_ptr(s1, p1); } + template inline typename boost::detail::sp_if_size_array::type allocate_shared(const A& allocator, @@ -139,76 +97,13 @@ namespace boost { boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); typedef boost::detail::array_deleter* D2; - p3 = reinterpret_cast(list); + p3 = reinterpret_cast(&list); p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->template init_list(p2, p3); + d2->template init(p2, p3); return boost::shared_ptr(s1, p1); } -#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) - template - inline typename boost::detail::sp_if_array::type - allocate_shared(const A& allocator, - std::initializer_list::type> list) { - typedef typename boost::detail::array_inner::type T1; - typedef typename boost::detail::array_base::type T2; - typedef const T2 T3; - T1* p1 = 0; - T2* p2 = 0; - T3* p3 = 0; - std::size_t n1 = list.size() * boost::detail::array_total::size; - boost::detail::allocate_array_helper a1(allocator, n1, &p2); - boost::detail::array_deleter d1(n1); - boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; - p3 = reinterpret_cast(list.begin()); - p1 = reinterpret_cast(p2); - D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->init_list(p2, p3); - return boost::shared_ptr(s1, p1); - } -#endif -#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - template - inline typename boost::detail::sp_if_array::type - allocate_shared(const A& allocator, std::size_t size, - typename boost::detail::array_base::type&& value) { - typedef typename boost::detail::array_inner::type T1; - typedef typename boost::detail::array_base::type T2; - T1* p1 = 0; - T2* p2 = 0; - std::size_t n1 = size * boost::detail::array_total::size; - boost::detail::allocate_array_helper a1(allocator, n1, &p2); - boost::detail::array_deleter d1(n1); - boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; - p1 = reinterpret_cast(p2); - D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->init(p2, boost::detail::sp_forward(value)); - return boost::shared_ptr(s1, p1); - } - template - inline typename boost::detail::sp_if_size_array::type - allocate_shared(const A& allocator, - typename boost::detail::array_base::type&& value) { - typedef typename boost::detail::array_inner::type T1; - typedef typename boost::detail::array_base::type T2; - enum { - N = boost::detail::array_total::size - }; - T1* p1 = 0; - T2* p2 = 0; - boost::detail::allocate_array_helper a1(allocator, &p2); - boost::detail::array_deleter d1; - boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; - p1 = reinterpret_cast(p2); - D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->init(p2, boost::detail::sp_forward(value)); - return boost::shared_ptr(s1, p1); - } -#endif -#endif + template inline typename boost::detail::sp_if_array::type allocate_shared_noinit(const A& allocator, std::size_t size) { @@ -226,6 +121,7 @@ namespace boost { d2->noinit(p2); return boost::shared_ptr(s1, p1); } + template inline typename boost::detail::sp_if_size_array::type allocate_shared_noinit(const A& allocator) { diff --git a/include/boost/smart_ptr/detail/allocate_array_helper.hpp b/include/boost/smart_ptr/detail/allocate_array_helper.hpp index 2eeea2d..1f358e7 100644 --- a/include/boost/smart_ptr/detail/allocate_array_helper.hpp +++ b/include/boost/smart_ptr/detail/allocate_array_helper.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Glen Joseph Fernandes + * Copyright (c) 2012-2014 Glen Joseph Fernandes * glenfe at live dot com * * Distributed under the Boost Software License, @@ -15,12 +15,15 @@ namespace boost { namespace detail { template class allocate_array_helper; + template class allocate_array_helper { template friend class allocate_array_helper; + typedef typename A::template rebind ::other A2; typedef typename A::template rebind::other A3; + public: typedef typename A2::value_type value_type; typedef typename A2::pointer pointer; @@ -29,30 +32,37 @@ namespace boost { typedef typename A2::const_reference const_reference; typedef typename A2::size_type size_type; typedef typename A2::difference_type difference_type; + template struct rebind { typedef allocate_array_helper other; }; + allocate_array_helper(const A& allocator_, std::size_t size_, T** data_) : allocator(allocator_), size(sizeof(T) * size_), data(data_) { } + template allocate_array_helper(const allocate_array_helper& other) : allocator(other.allocator), size(other.size), data(other.data) { } + pointer address(reference value) const { return allocator.address(value); } + const_pointer address(const_reference value) const { return allocator.address(value); } + size_type max_size() const { return allocator.max_size(); } + pointer allocate(size_type count, const void* value = 0) { std::size_t a1 = boost::alignment_of::value; std::size_t n1 = count * sizeof(Y) + a1 - 1; @@ -64,37 +74,46 @@ namespace boost { *data = reinterpret_cast(p2); return reinterpret_cast(p1); } + void deallocate(pointer memory, size_type count) { std::size_t a1 = boost::alignment_of::value; std::size_t n1 = count * sizeof(Y) + a1 - 1; char* p1 = reinterpret_cast(memory); A3(allocator).deallocate(p1, n1 + size); } + void construct(pointer memory, const Y& value) { allocator.construct(memory, value); } + void destroy(pointer memory) { allocator.destroy(memory); } + template bool operator==(const allocate_array_helper& other) const { return allocator == other.allocator; } + template bool operator!=(const allocate_array_helper& other) const { return !(*this == other); } + private: A2 allocator; std::size_t size; T** data; }; + template class allocate_array_helper { template friend class allocate_array_helper; + typedef typename A::template rebind ::other A2; typedef typename A::template rebind::other A3; + public: typedef typename A2::value_type value_type; typedef typename A2::pointer pointer; @@ -103,28 +122,35 @@ namespace boost { typedef typename A2::const_reference const_reference; typedef typename A2::size_type size_type; typedef typename A2::difference_type difference_type; + template struct rebind { typedef allocate_array_helper other; }; + allocate_array_helper(const A& allocator_, T** data_) : allocator(allocator_), data(data_) { } + template allocate_array_helper(const allocate_array_helper& other) : allocator(other.allocator), data(other.data) { } + pointer address(reference value) const { return allocator.address(value); } + const_pointer address(const_reference value) const { return allocator.address(value); } + size_type max_size() const { return allocator.max_size(); } + pointer allocate(size_type count, const void* value = 0) { std::size_t a1 = boost::alignment_of::value; std::size_t n1 = count * sizeof(Y) + a1 - 1; @@ -136,30 +162,37 @@ namespace boost { *data = reinterpret_cast(p2); return reinterpret_cast(p1); } + void deallocate(pointer memory, size_type count) { std::size_t a1 = boost::alignment_of::value; std::size_t n1 = count * sizeof(Y) + a1 - 1; char* p1 = reinterpret_cast(memory); A3(allocator).deallocate(p1, n1 + N1); } + void construct(pointer memory, const Y& value) { allocator.construct(memory, value); } + void destroy(pointer memory) { allocator.destroy(memory); } + template bool operator==(const allocate_array_helper& other) const { return allocator == other.allocator; } + template bool operator!=(const allocate_array_helper& other) const { return !(*this == other); } + private: enum { N1 = N * sizeof(T) }; + A2 allocator; T** data; }; diff --git a/include/boost/smart_ptr/detail/array_deleter.hpp b/include/boost/smart_ptr/detail/array_deleter.hpp index 20f84d1..6db78c8 100644 --- a/include/boost/smart_ptr/detail/array_deleter.hpp +++ b/include/boost/smart_ptr/detail/array_deleter.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Glen Joseph Fernandes + * Copyright (c) 2012-2014 Glen Joseph Fernandes * glenfe at live dot com * * Distributed under the Boost Software License, @@ -10,12 +10,12 @@ #define BOOST_SMART_PTR_DETAIL_ARRAY_DELETER_HPP #include -#include namespace boost { namespace detail { template class array_deleter; + template class array_deleter { public: @@ -23,98 +23,77 @@ namespace boost { : size(size_), object(0) { } + ~array_deleter() { if (object) { array_destroy(object, size); } } + void init(T* memory) { array_init(memory, size); object = memory; } -#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - void init(T* memory, T&& value) { - array_init_value(memory, size, sp_forward(value)); - object = memory; - } -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - template - void init(T* memory, Args&&... args) { - array_init_args(memory, size, sp_forward(args)...); - object = memory; - } -#endif -#endif - void init_list(T* memory, const T* list) { - array_init_list(memory, size, list); - object = memory; - } + template - void init_list(T* memory, const T* list) { - array_init_list(memory, size, list); + void init(T* memory, const T* list) { + array_init(memory, size, list); object = memory; } + void noinit(T* memory) { array_noinit(memory, size); object = memory; } + void operator()(const void*) { if (object) { array_destroy(object, size); object = 0; } } + private: std::size_t size; T* object; }; + template class array_deleter { public: array_deleter() : object(0) { } + ~array_deleter() { if (object) { array_destroy(object, N); } } + void init(T* memory) { array_init(memory, N); object = memory; } -#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - void init(T* memory, T&& value) { - array_init_value(memory, N, sp_forward(value)); - object = memory; - } -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - template - void init(T* memory, Args&&... args) { - array_init_args(memory, N, sp_forward(args)...); - object = memory; - } -#endif -#endif - void init_list(T* memory, const T* list) { - array_init_list(memory, N, list); - object = memory; - } + template - void init_list(T* memory, const T* list) { - array_init_list(memory, N, list); + void init(T* memory, const T* list) { + array_init(memory, N, list); object = memory; } + void noinit(T* memory) { array_noinit(memory, N); object = memory; } + void operator()(const void*) { if (object) { array_destroy(object, N); object = 0; } } + private: T* object; }; diff --git a/include/boost/smart_ptr/detail/array_traits.hpp b/include/boost/smart_ptr/detail/array_traits.hpp index 8ef7874..712efbb 100644 --- a/include/boost/smart_ptr/detail/array_traits.hpp +++ b/include/boost/smart_ptr/detail/array_traits.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Glen Joseph Fernandes + * Copyright (c) 2012-2014 Glen Joseph Fernandes * glenfe at live dot com * * Distributed under the Boost Software License, @@ -17,32 +17,39 @@ namespace boost { struct array_base { typedef typename boost::remove_cv::type type; }; + template struct array_base { typedef typename array_base::type type; }; + template struct array_base { typedef typename array_base::type type; }; + template struct array_total { enum { size = 1 }; }; + template struct array_total { enum { size = N * array_total::size }; }; + template struct array_inner; + template struct array_inner { typedef T type; }; + template struct array_inner { typedef T type; diff --git a/include/boost/smart_ptr/detail/array_utility.hpp b/include/boost/smart_ptr/detail/array_utility.hpp index 3cf36d7..cea2865 100644 --- a/include/boost/smart_ptr/detail/array_utility.hpp +++ b/include/boost/smart_ptr/detail/array_utility.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Glen Joseph Fernandes + * Copyright (c) 2012-2014 Glen Joseph Fernandes * glenfe at live dot com * * Distributed under the Boost Software License, @@ -18,25 +18,30 @@ namespace boost { template inline void array_destroy(T*, std::size_t, boost::true_type) { } + template inline void array_destroy(T* memory, std::size_t size, boost::false_type) { for (std::size_t i = size; i > 0; ) { memory[--i].~T(); } } + template inline void array_destroy(T* memory, std::size_t size) { boost::has_trivial_destructor type; array_destroy(memory, size, type); } + template - inline void array_init(T* memory, std::size_t size, boost::true_type) { + inline void array_value(T* memory, std::size_t size, boost::true_type) { for (std::size_t i = 0; i < size; i++) { - memory[i] = T(); + void* p1 = memory + i; + ::new(p1) T(); } } + template - inline void array_init(T* memory, std::size_t size, boost::false_type) { + inline void array_value(T* memory, std::size_t size, boost::false_type) { #if !defined(BOOST_NO_EXCEPTIONS) std::size_t i = 0; try { @@ -55,77 +60,15 @@ namespace boost { } #endif } + template inline void array_init(T* memory, std::size_t size) { boost::has_trivial_default_constructor type; - array_init(memory, size, type); - } -#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - template - inline void array_init_value(T* memory, std::size_t size, T&& value) { -#if !defined(BOOST_NO_EXCEPTIONS) - std::size_t i = 0; - try { - for (; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T(value); - } - } catch (...) { - array_destroy(memory, i); - throw; - } -#else - for (std::size_t i = 0; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T(value); - } -#endif - } -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - template - inline void array_init_args(T* memory, std::size_t size, Args&&... args) { -#if !defined(BOOST_NO_EXCEPTIONS) - std::size_t i = 0; - try { - for (; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T(args...); - } - } catch (...) { - array_destroy(memory, i); - throw; - } -#else - for (std::size_t i = 0; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T(args...); - } -#endif - } -#endif -#endif - template - inline void array_init_list(T* memory, std::size_t size, const T* list) { -#if !defined(BOOST_NO_EXCEPTIONS) - std::size_t i = 0; - try { - for (; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T(list[i]); - } - } catch (...) { - array_destroy(memory, i); - throw; - } -#else - for (std::size_t i = 0; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T(list[i]); - } -#endif + array_value(memory, size, type); } + template - inline void array_init_list(T* memory, std::size_t size, const T* list) { + inline void array_init(T* memory, std::size_t size, const T* list) { #if !defined(BOOST_NO_EXCEPTIONS) std::size_t i = 0; try { @@ -144,11 +87,13 @@ namespace boost { } #endif } + template - inline void array_noinit(T*, std::size_t, boost::true_type) { + inline void array_default(T*, std::size_t, boost::true_type) { } + template - inline void array_noinit(T* memory, std::size_t size, boost::false_type) { + inline void array_default(T* memory, std::size_t size, boost::false_type) { #if !defined(BOOST_NO_EXCEPTIONS) std::size_t i = 0; try { @@ -167,10 +112,11 @@ namespace boost { } #endif } + template inline void array_noinit(T* memory, std::size_t size) { boost::has_trivial_default_constructor type; - array_noinit(memory, size, type); + array_default(memory, size, type); } } } diff --git a/include/boost/smart_ptr/detail/make_array_helper.hpp b/include/boost/smart_ptr/detail/make_array_helper.hpp index 6cf0483..cc1fc44 100644 --- a/include/boost/smart_ptr/detail/make_array_helper.hpp +++ b/include/boost/smart_ptr/detail/make_array_helper.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Glen Joseph Fernandes + * Copyright (c) 2012-2104 Glen Joseph Fernandes * glenfe at live dot com * * Distributed under the Boost Software License, @@ -15,10 +15,12 @@ namespace boost { namespace detail { template class make_array_helper; + template class make_array_helper { template friend class make_array_helper; + public: typedef Y value_type; typedef Y* pointer; @@ -27,28 +29,35 @@ namespace boost { typedef const Y& const_reference; typedef std::size_t size_type; typedef ptrdiff_t difference_type; + template struct rebind { typedef make_array_helper other; }; + make_array_helper(std::size_t size_, T** data_) : size(sizeof(T) * size_), data(data_) { } + template make_array_helper(const make_array_helper& other) : size(other.size), data(other.data) { } + pointer address(reference value) const { return &value; } + const_pointer address(const_reference value) const { return &value; } + size_type max_size() const { return static_cast(-1) / sizeof(Y); } + pointer allocate(size_type count, const void* = 0) { std::size_t a1 = boost::alignment_of::value; std::size_t n1 = count * sizeof(Y) + a1 - 1; @@ -60,33 +69,41 @@ namespace boost { *data = reinterpret_cast(p2); return reinterpret_cast(p1); } + void deallocate(pointer memory, size_type) { void* p1 = memory; ::operator delete(p1); } + void construct(pointer memory, const Y& value) { void* p1 = memory; ::new(p1) Y(value); } + void destroy(pointer memory) { memory->~Y(); } + template bool operator==(const make_array_helper&) const { return true; } + template bool operator!=(const make_array_helper& other) const { return !(*this == other); } + private: std::size_t size; T** data; }; + template class make_array_helper { template friend class make_array_helper; + public: typedef Y value_type; typedef Y* pointer; @@ -95,26 +112,33 @@ namespace boost { typedef const Y& const_reference; typedef std::size_t size_type; typedef ptrdiff_t difference_type; + template struct rebind { typedef make_array_helper other; }; + make_array_helper(T** data_) : data(data_) { } + template make_array_helper(const make_array_helper& other) : data(other.data) { } + pointer address(reference value) const { return &value; } + const_pointer address(const_reference value) const { return &value; } + size_type max_size() const { return static_cast(-1) / sizeof(Y); } + pointer allocate(size_type count, const void* = 0) { std::size_t a1 = boost::alignment_of::value; std::size_t n1 = count * sizeof(Y) + a1 - 1; @@ -126,29 +150,36 @@ namespace boost { *data = reinterpret_cast(p2); return reinterpret_cast(p1); } + void deallocate(pointer memory, size_type) { void* p1 = memory; ::operator delete(p1); } + void construct(pointer memory, const Y& value) { void* p1 = memory; ::new(p1) Y(value); } + void destroy(pointer memory) { memory->~Y(); } + template bool operator==(const make_array_helper&) const { return true; } + template bool operator!=(const make_array_helper& other) const { return !(*this == other); } + private: enum { N1 = N * sizeof(T) }; + T** data; }; } diff --git a/include/boost/smart_ptr/detail/sp_if_array.hpp b/include/boost/smart_ptr/detail/sp_if_array.hpp index 661e178..bbd0f3c 100644 --- a/include/boost/smart_ptr/detail/sp_if_array.hpp +++ b/include/boost/smart_ptr/detail/sp_if_array.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Glen Joseph Fernandes + * Copyright (c) 2012-2014 Glen Joseph Fernandes * glenfe at live dot com * * Distributed under the Boost Software License, @@ -15,12 +15,15 @@ namespace boost { namespace detail { template struct sp_if_array; + template struct sp_if_array { typedef boost::shared_ptr type; }; + template struct sp_if_size_array; + template struct sp_if_size_array { typedef boost::shared_ptr type; diff --git a/include/boost/smart_ptr/make_shared_array.hpp b/include/boost/smart_ptr/make_shared_array.hpp index eb0578d..7dc952e 100644 --- a/include/boost/smart_ptr/make_shared_array.hpp +++ b/include/boost/smart_ptr/make_shared_array.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Glen Joseph Fernandes + * Copyright (c) 2012-2014 Glen Joseph Fernandes * glenfe at live dot com * * Distributed under the Boost Software License, @@ -14,9 +14,6 @@ #include #include #include -#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) -#include -#endif namespace boost { template @@ -36,67 +33,27 @@ namespace boost { d2->init(p2); return boost::shared_ptr(s1, p1); } -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - template - inline typename boost::detail::sp_if_array::type - make_shared(std::size_t size, Args&&... args) { - typedef typename boost::detail::array_inner::type T1; - typedef typename boost::detail::array_base::type T2; - T1* p1 = 0; - T2* p2 = 0; - std::size_t n1 = size * boost::detail::array_total::size; - boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1(n1); - boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; - p1 = reinterpret_cast(p2); - D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->init(p2, boost::detail::sp_forward(args)...); - return boost::shared_ptr(s1, p1); - } - template - inline typename boost::detail::sp_if_size_array::type - make_shared(Args&&... args) { - typedef typename boost::detail::array_inner::type T1; - typedef typename boost::detail::array_base::type T2; - enum { - N = boost::detail::array_total::size - }; - T1* p1 = 0; - T2* p2 = 0; - boost::detail::make_array_helper a1(&p2); - boost::detail::array_deleter d1; - boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; - p1 = reinterpret_cast(p2); - D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->init(p2, boost::detail::sp_forward(args)...); - return boost::shared_ptr(s1, p1); - } -#endif -#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) + template inline typename boost::detail::sp_if_size_array::type - make_shared(const T& list) { + make_shared() { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; - typedef const T2 T3; enum { N = boost::detail::array_total::size }; T1* p1 = 0; T2* p2 = 0; - T3* p3 = 0; boost::detail::make_array_helper a1(&p2); boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); typedef boost::detail::array_deleter* D2; - p3 = reinterpret_cast(list); p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->init_list(p2, p3); + d2->init(p2); return boost::shared_ptr(s1, p1); } + template inline typename boost::detail::sp_if_array::type make_shared(std::size_t size, @@ -115,12 +72,13 @@ namespace boost { boost::detail::array_deleter d1(n1); boost::shared_ptr s1(p1, d1, a1); typedef boost::detail::array_deleter* D2; - p3 = reinterpret_cast(list); + p3 = reinterpret_cast(&list); p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->template init_list(p2, p3); + d2->template init(p2, p3); return boost::shared_ptr(s1, p1); } + template inline typename boost::detail::sp_if_size_array::type make_shared(const typename boost::detail::array_inner::type& list) { @@ -138,74 +96,13 @@ namespace boost { boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); typedef boost::detail::array_deleter* D2; - p3 = reinterpret_cast(list); + p3 = reinterpret_cast(&list); p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->template init_list(p2, p3); + d2->template init(p2, p3); return boost::shared_ptr(s1, p1); } -#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) - template - inline typename boost::detail::sp_if_array::type - make_shared(std::initializer_list::type> list) { - typedef typename boost::detail::array_inner::type T1; - typedef typename boost::detail::array_base::type T2; - typedef const T2 T3; - T1* p1 = 0; - T2* p2 = 0; - T3* p3 = 0; - std::size_t n1 = list.size() * boost::detail::array_total::size; - boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1(n1); - boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; - p3 = reinterpret_cast(list.begin()); - p1 = reinterpret_cast(p2); - D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->init_list(p2, p3); - return boost::shared_ptr(s1, p1); - } -#endif -#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - template - inline typename boost::detail::sp_if_array::type - make_shared(std::size_t size, - typename boost::detail::array_base::type&& value) { - typedef typename boost::detail::array_inner::type T1; - typedef typename boost::detail::array_base::type T2; - T1* p1 = 0; - T2* p2 = 0; - std::size_t n1 = size * boost::detail::array_total::size; - boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1(n1); - boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; - p1 = reinterpret_cast(p2); - D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->init(p2, boost::detail::sp_forward(value)); - return boost::shared_ptr(s1, p1); - } - template - inline typename boost::detail::sp_if_size_array::type - make_shared(typename boost::detail::array_base::type&& value) { - typedef typename boost::detail::array_inner::type T1; - typedef typename boost::detail::array_base::type T2; - enum { - N = boost::detail::array_total::size - }; - T1* p1 = 0; - T2* p2 = 0; - boost::detail::make_array_helper a1(&p2); - boost::detail::array_deleter d1; - boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; - p1 = reinterpret_cast(p2); - D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->init(p2, boost::detail::sp_forward(value)); - return boost::shared_ptr(s1, p1); - } -#endif -#endif + template inline typename boost::detail::sp_if_array::type make_shared_noinit(std::size_t size) { @@ -223,6 +120,7 @@ namespace boost { d2->noinit(p2); return boost::shared_ptr(s1, p1); } + template inline typename boost::detail::sp_if_size_array::type make_shared_noinit() { diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index f90316e..60cf992 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -137,22 +137,16 @@ import testing ; [ compile-fail array_fail_array_access.cpp ] [ run make_shared_array_test.cpp ] - [ run make_shared_arrays_test.cpp ] - [ run make_shared_array_create_test.cpp ] - [ run make_shared_array_init_test.cpp : : : gcc-4.6.3_0x:-fno-deduce-init-list ] - [ run make_shared_arrays_create_test.cpp : : : gcc-4.6.3_0x:-fno-deduce-init-list ] - [ run make_shared_arrays_init_test.cpp : : : gcc-4.6.3_0x:-fno-deduce-init-list ] + [ run make_shared_arrays_test.cpp : : : gcc-4.6.3_0x:-fno-deduce-init-list ] [ run make_shared_array_throws_test.cpp ] [ run make_shared_array_esft_test.cpp ] - [ run make_shared_array_args_test.cpp ] + [ run make_shared_array_noinit_test.cpp ] + [ run make_shared_array_value_test.cpp ] [ run allocate_shared_array_test.cpp ] - [ run allocate_shared_arrays_test.cpp ] - [ run allocate_shared_array_create_test.cpp ] - [ run allocate_shared_array_init_test.cpp : : : gcc-4.6.3_0x:-fno-deduce-init-list ] - [ run allocate_shared_arrays_create_test.cpp : : : gcc-4.6.3_0x:-fno-deduce-init-list ] - [ run allocate_shared_arrays_init_test.cpp : : : gcc-4.6.3_0x:-fno-deduce-init-list ] + [ run allocate_shared_arrays_test.cpp : : : gcc-4.6.3_0x:-fno-deduce-init-list ] [ run allocate_shared_array_throws_test.cpp ] [ run allocate_shared_array_esft_test.cpp ] - [ run allocate_shared_array_args_test.cpp ] + [ run allocate_shared_array_noinit_test.cpp ] + [ run allocate_shared_array_value_test.cpp ] ; } diff --git a/test/allocate_shared_array_args_test.cpp b/test/allocate_shared_array_args_test.cpp deleted file mode 100644 index f3d38b6..0000000 --- a/test/allocate_shared_array_args_test.cpp +++ /dev/null @@ -1,173 +0,0 @@ -// allocate_shared_array_args_test.cpp -// -// Copyright 2007-2009, 2012 Peter Dimov -// -// 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 - -#include -#include -#include -#include -#include - -class X -{ -private: - - X( X const & ); - X & operator=( X const & ); - - void * operator new[]( std::size_t n ); - void operator delete[]( void * p ); - -public: - - static int instances; - - int v; - - explicit X( int a1 = 0, int a2 = 0, int a3 = 0, int a4 = 0, int a5 = 0, int a6 = 0, int a7 = 0, int a8 = 0, int a9 = 0 ): v( a1+a2+a3+a4+a5+a6+a7+a8+a9 ) - { - ++instances; - } - - ~X() - { - --instances; - } -}; - -int X::instances = 0; - -int main() -{ - BOOST_TEST( X::instances == 0 ); - - { - boost::shared_ptr< X[] > px = boost::allocate_shared< X[] >( std::allocator(), 2 ); - - BOOST_TEST( X::instances == 2 ); - BOOST_TEST( px[0].v == 0 ); - BOOST_TEST( px[1].v == 0 ); - - px.reset(); - - BOOST_TEST( X::instances == 0 ); - } - -#if !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) - - { - boost::shared_ptr< X[] > px = boost::allocate_shared< X[] >( std::allocator(), 2, 1 ); - - BOOST_TEST( X::instances == 2 ); - BOOST_TEST( px[0].v == 1 ); - BOOST_TEST( px[1].v == 1 ); - - px.reset(); - - BOOST_TEST( X::instances == 0 ); - } - - { - boost::shared_ptr< X[] > px = boost::allocate_shared< X[] >( std::allocator(), 2, 1, 2 ); - - BOOST_TEST( X::instances == 2 ); - BOOST_TEST( px[0].v == 1+2 ); - BOOST_TEST( px[1].v == 1+2 ); - - px.reset(); - - BOOST_TEST( X::instances == 0 ); - } - - { - boost::shared_ptr< X[] > px = boost::allocate_shared< X[] >( std::allocator(), 2, 1, 2, 3 ); - - BOOST_TEST( X::instances == 2 ); - BOOST_TEST( px[0].v == 1+2+3 ); - BOOST_TEST( px[1].v == 1+2+3 ); - - px.reset(); - - BOOST_TEST( X::instances == 0 ); - } - - { - boost::shared_ptr< X[] > px = boost::allocate_shared< X[] >( std::allocator(), 2, 1, 2, 3, 4 ); - - BOOST_TEST( X::instances == 2 ); - BOOST_TEST( px[0].v == 1+2+3+4 ); - BOOST_TEST( px[1].v == 1+2+3+4 ); - - px.reset(); - - BOOST_TEST( X::instances == 0 ); - } - - { - boost::shared_ptr< X[] > px = boost::allocate_shared< X[] >( std::allocator(), 2, 1, 2, 3, 4, 5 ); - - BOOST_TEST( X::instances == 2 ); - BOOST_TEST( px[0].v == 1+2+3+4+5 ); - BOOST_TEST( px[1].v == 1+2+3+4+5 ); - - px.reset(); - - BOOST_TEST( X::instances == 0 ); - } - - { - boost::shared_ptr< X[] > px = boost::allocate_shared< X[] >( std::allocator(), 2, 1, 2, 3, 4, 5, 6 ); - - BOOST_TEST( X::instances == 2 ); - BOOST_TEST( px[0].v == 1+2+3+4+5+6 ); - BOOST_TEST( px[1].v == 1+2+3+4+5+6 ); - - px.reset(); - - BOOST_TEST( X::instances == 0 ); - } - - { - boost::shared_ptr< X[] > px = boost::allocate_shared< X[] >( std::allocator(), 2, 1, 2, 3, 4, 5, 6, 7 ); - - BOOST_TEST( X::instances == 2 ); - BOOST_TEST( px[0].v == 1+2+3+4+5+6+7 ); - BOOST_TEST( px[1].v == 1+2+3+4+5+6+7 ); - - px.reset(); - - BOOST_TEST( X::instances == 0 ); - } - - { - boost::shared_ptr< X[] > px = boost::allocate_shared< X[] >( std::allocator(), 2, 1, 2, 3, 4, 5, 6, 7, 8 ); - - BOOST_TEST( X::instances == 2 ); - BOOST_TEST( px[0].v == 1+2+3+4+5+6+7+8 ); - BOOST_TEST( px[1].v == 1+2+3+4+5+6+7+8 ); - - px.reset(); - - BOOST_TEST( X::instances == 0 ); - } - - { - boost::shared_ptr< X[] > px = boost::allocate_shared< X[] >( std::allocator(), 2, 1, 2, 3, 4, 5, 6, 7, 8, 9 ); - - BOOST_TEST( X::instances == 2 ); - BOOST_TEST( px[0].v == 1+2+3+4+5+6+7+8+9 ); - BOOST_TEST( px[1].v == 1+2+3+4+5+6+7+8+9 ); - - px.reset(); - - BOOST_TEST( X::instances == 0 ); - } - -#endif - - return boost::report_errors(); -} diff --git a/test/allocate_shared_array_create_test.cpp b/test/allocate_shared_array_create_test.cpp deleted file mode 100644 index 90b6b96..0000000 --- a/test/allocate_shared_array_create_test.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2012 Glen Joseph Fernandes - * glenfe at live dot com - * - * Distributed under the Boost Software License, - * Version 1.0. (See accompanying file LICENSE_1_0.txt - * or copy at http://boost.org/LICENSE_1_0.txt) - */ -#include -#include - -class type { -public: - static int instances; - explicit type(int a=0, int b=0, int c=0, int d=0, int e=0, int f=0, int g=0, int h=0, int i=0) - : a(a), b(b), c(c), d(d), e(e), f(f), g(g), h(h), i(i) { - instances++; - } - ~type() { - instances--; - } - const int a; - const int b; - const int c; - const int d; - const int e; - const int f; - const int g; - const int h; - const int i; -private: - type(const type&); - type& operator=(const type&); -}; - -int type::instances = 0; - -int main() { -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2, 1, 2, 3, 4, 5, 6, 7, 8, 9); - BOOST_TEST(type::instances == 2); - BOOST_TEST(a1[0].a == 1); - BOOST_TEST(a1[0].d == 4); - BOOST_TEST(a1[1].f == 6); - BOOST_TEST(a1[1].i == 9); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 1, 2, 3, 4, 5, 6, 7, 8, 9); - BOOST_TEST(type::instances == 2); - BOOST_TEST(a1[0].a == 1); - BOOST_TEST(a1[0].d == 4); - BOOST_TEST(a1[1].f == 6); - BOOST_TEST(a1[1].i == 9); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2, 1, 2, 3, 4, 5, 6, 7); - BOOST_TEST(type::instances == 4); - BOOST_TEST(a1[0][0].a == 1); - BOOST_TEST(a1[0][1].d == 4); - BOOST_TEST(a1[1][0].f == 6); - BOOST_TEST(a1[1][1].i == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 1, 2, 3, 4, 5, 6, 7); - BOOST_TEST(type::instances == 4); - BOOST_TEST(a1[0][0].a == 1); - BOOST_TEST(a1[0][1].d == 4); - BOOST_TEST(a1[1][0].f == 6); - BOOST_TEST(a1[1][1].i == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2, 1, 2, 3, 4, 5); - BOOST_TEST(type::instances == 8); - BOOST_TEST(a1[0][0][0].a == 1); - BOOST_TEST(a1[0][1][0].c == 3); - BOOST_TEST(a1[1][0][1].e == 5); - BOOST_TEST(a1[1][1][1].i == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 1, 2, 3, 4, 5); - BOOST_TEST(type::instances == 8); - BOOST_TEST(a1[0][0][0].a == 1); - BOOST_TEST(a1[0][1][0].c == 3); - BOOST_TEST(a1[1][0][1].e == 5); - BOOST_TEST(a1[1][1][1].i == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2, 1, 2, 3); - BOOST_TEST(type::instances == 16); - BOOST_TEST(a1[0][0][0][1].a == 1); - BOOST_TEST(a1[0][0][1][0].c == 3); - BOOST_TEST(a1[0][1][0][0].f == 0); - BOOST_TEST(a1[1][0][0][0].i == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 1, 2, 3); - BOOST_TEST(type::instances == 16); - BOOST_TEST(a1[0][0][0][1].a == 1); - BOOST_TEST(a1[0][0][1][0].c == 3); - BOOST_TEST(a1[0][1][0][0].f == 0); - BOOST_TEST(a1[1][0][0][0].i == 0); - } -#endif - return boost::report_errors(); -} diff --git a/test/allocate_shared_array_esft_test.cpp b/test/allocate_shared_array_esft_test.cpp index cea73c6..b342366 100644 --- a/test/allocate_shared_array_esft_test.cpp +++ b/test/allocate_shared_array_esft_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Glen Joseph Fernandes + * Copyright (c) 2012-2014 Glen Joseph Fernandes * glenfe at live dot com * * Distributed under the Boost Software License, @@ -14,12 +14,15 @@ class type : public boost::enable_shared_from_this { public: static unsigned int instances; + explicit type() { instances++; } + ~type() { instances--; } + private: type(const type&); type& operator=(const type&); @@ -38,6 +41,7 @@ int main() { BOOST_TEST(type::instances == 3); } } + BOOST_TEST(type::instances == 0); { boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator(), 3); @@ -48,5 +52,6 @@ int main() { BOOST_TEST(type::instances == 3); } } + return boost::report_errors(); } diff --git a/test/allocate_shared_array_init_test.cpp b/test/allocate_shared_array_init_test.cpp deleted file mode 100644 index c75b41f..0000000 --- a/test/allocate_shared_array_init_test.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2012 Glen Joseph Fernandes - * glenfe at live dot com - * - * Distributed under the Boost Software License, - * Version 1.0. (See accompanying file LICENSE_1_0.txt - * or copy at http://boost.org/LICENSE_1_0.txt) - */ -#include -#include - -class type { -public: - type(int value) - : value(value) { - } - const int value; -private: - type& operator=(const type&); -}; - -int main() { -#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); - BOOST_TEST(a1[0] == 0); - BOOST_TEST(a1[1] == 1); - BOOST_TEST(a1[2] == 2); - BOOST_TEST(a1[3] == 3); - } - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); - BOOST_TEST(a1[0] == 0); - BOOST_TEST(a1[1] == 1); - BOOST_TEST(a1[2] == 2); - BOOST_TEST(a1[3] == 3); - } - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); - BOOST_TEST(a1[0].value == 0); - BOOST_TEST(a1[1].value == 1); - BOOST_TEST(a1[2].value == 2); - BOOST_TEST(a1[3].value == 3); - } - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); - BOOST_TEST(a1[0].value == 0); - BOOST_TEST(a1[1].value == 1); - BOOST_TEST(a1[2].value == 2); - BOOST_TEST(a1[3].value == 3); - } -#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); - BOOST_TEST(a1[0] == 0); - BOOST_TEST(a1[1] == 1); - BOOST_TEST(a1[2] == 2); - BOOST_TEST(a1[3] == 3); - } - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); - BOOST_TEST(a1[0] == 0); - BOOST_TEST(a1[1] == 1); - BOOST_TEST(a1[2] == 2); - BOOST_TEST(a1[3] == 3); - } - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); - BOOST_TEST(a1[0].value == 0); - BOOST_TEST(a1[1].value == 1); - BOOST_TEST(a1[2].value == 2); - BOOST_TEST(a1[3].value == 3); - } - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1, 2, 3 }); - BOOST_TEST(a1[0].value == 0); - BOOST_TEST(a1[1].value == 1); - BOOST_TEST(a1[2].value == 2); - BOOST_TEST(a1[3].value == 3); - } -#endif -#endif - return boost::report_errors(); -} diff --git a/test/allocate_shared_array_noinit_test.cpp b/test/allocate_shared_array_noinit_test.cpp new file mode 100644 index 0000000..6c8ff3d --- /dev/null +++ b/test/allocate_shared_array_noinit_test.cpp @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2012-2014 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include +#include +#include + +class type { +public: + static unsigned int instances; + + explicit type() { + instances++; + } + + ~type() { + instances--; + } + +private: + type(const type&); + type& operator=(const type&); +}; + +unsigned int type::instances = 0; + +int main() { + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator(), 3); + int* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + } + + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator()); + int* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + } + + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator(), 2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + } + + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator()); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + } + + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator(), 3); + const int* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + } + + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator()); + const int* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + } + + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator(), 2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + } + + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator()); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + } + + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator(), 3); + type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + boost::weak_ptr w1 = a1; + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator()); + type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + boost::weak_ptr w1 = a1; + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator(), 2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 4); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator()); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 4); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator(), 3); + const type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator()); + const type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator(), 2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 4); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator()); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 4); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + return boost::report_errors(); +} diff --git a/test/allocate_shared_array_test.cpp b/test/allocate_shared_array_test.cpp index f27e5e8..737e736 100644 --- a/test/allocate_shared_array_test.cpp +++ b/test/allocate_shared_array_test.cpp @@ -1,11 +1,11 @@ /* - * Copyright (c) 2012 Glen Joseph Fernandes + * Copyright (c) 2012-2014 Glen Joseph Fernandes * glenfe at live dot com * - * Distributed under the Boost Software License, - * Version 1.0. (See accompanying file LICENSE_1_0.txt + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt * or copy at http://boost.org/LICENSE_1_0.txt) - */ +*/ #include #include #include @@ -14,17 +14,18 @@ class type { public: static unsigned int instances; - explicit type(int = 0, int = 0) - : member() { + + explicit type() { instances++; } + ~type() { instances--; } + private: type(const type&); type& operator=(const type&); - double member; }; unsigned int type::instances = 0; @@ -40,6 +41,38 @@ int main() { BOOST_TEST(a1[1] == 0); BOOST_TEST(a1[2] == 0); } + + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator()); + int* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 0); + BOOST_TEST(a1[2] == 0); + } + + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a1[0][0] == 0); + BOOST_TEST(a1[0][1] == 0); + BOOST_TEST(a1[1][0] == 0); + BOOST_TEST(a1[1][1] == 0); + } + + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator()); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a1[0][0] == 0); + BOOST_TEST(a1[0][1] == 0); + BOOST_TEST(a1[1][0] == 0); + BOOST_TEST(a1[1][1] == 0); + } + { boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 3); const int* a2 = a1.get(); @@ -50,6 +83,38 @@ int main() { BOOST_TEST(a1[1] == 0); BOOST_TEST(a1[2] == 0); } + + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator()); + const int* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 0); + BOOST_TEST(a1[2] == 0); + } + + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a1[0][0] == 0); + BOOST_TEST(a1[0][1] == 0); + BOOST_TEST(a1[1][0] == 0); + BOOST_TEST(a1[1][1] == 0); + } + + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator()); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a1[0][0] == 0); + BOOST_TEST(a1[0][1] == 0); + BOOST_TEST(a1[1][0] == 0); + BOOST_TEST(a1[1][1] == 0); + } + BOOST_TEST(type::instances == 0); { boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 3); @@ -62,6 +127,40 @@ int main() { a1.reset(); BOOST_TEST(type::instances == 0); } + + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator()); + type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + boost::weak_ptr w1 = a1; + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 4); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator()); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 4); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); { boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 3); @@ -73,109 +172,10 @@ int main() { a1.reset(); BOOST_TEST(type::instances == 0); } -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + BOOST_TEST(type::instances == 0); { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 3, 1, 5); - type* a2 = a1.get(); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(a2 != 0); - BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); - BOOST_TEST(type::instances == 3); - boost::weak_ptr w1 = a1; - a1.reset(); - BOOST_TEST(type::instances == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 1, 5); - type* a2 = a1.get(); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(a2 != 0); - BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); - BOOST_TEST(type::instances == 3); - boost::weak_ptr w1 = a1; - a1.reset(); - BOOST_TEST(type::instances == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 3, 1, 5); - const type* a2 = a1.get(); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(a2 != 0); - BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); - BOOST_TEST(type::instances == 3); - a1.reset(); - BOOST_TEST(type::instances == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 1, 5); - const type* a2 = a1.get(); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(a2 != 0); - BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); - BOOST_TEST(type::instances == 3); - a1.reset(); - BOOST_TEST(type::instances == 0); - } -#endif - { - boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator(), 3); - int* a2 = a1.get(); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(a2 != 0); - BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); - } - { - boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator()); - int* a2 = a1.get(); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(a2 != 0); - BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); - } - { - boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator(), 3); - const int* a2 = a1.get(); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(a2 != 0); - BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); - } - { - boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator()); - const int* a2 = a1.get(); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(a2 != 0); - BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator(), 3); - type* a2 = a1.get(); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(a2 != 0); - BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); - BOOST_TEST(type::instances == 3); - boost::weak_ptr w1 = a1; - a1.reset(); - BOOST_TEST(type::instances == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator()); - type* a2 = a1.get(); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(a2 != 0); - BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); - BOOST_TEST(type::instances == 3); - boost::weak_ptr w1 = a1; - a1.reset(); - BOOST_TEST(type::instances == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator(), 3); + boost::shared_ptr a1 = boost::allocate_shared(std::allocator()); const type* a2 = a1.get(); BOOST_TEST(a1.use_count() == 1); BOOST_TEST(a2 != 0); @@ -184,16 +184,26 @@ int main() { a1.reset(); BOOST_TEST(type::instances == 0); } + BOOST_TEST(type::instances == 0); { - boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator()); - const type* a2 = a1.get(); + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2); + BOOST_TEST(a1.get() != 0); BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(a2 != 0); - BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); - BOOST_TEST(type::instances == 3); + BOOST_TEST(type::instances == 4); a1.reset(); BOOST_TEST(type::instances == 0); } + + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator()); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 4); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + return boost::report_errors(); } diff --git a/test/allocate_shared_array_throws_test.cpp b/test/allocate_shared_array_throws_test.cpp index bb5ac52..79beaeb 100644 --- a/test/allocate_shared_array_throws_test.cpp +++ b/test/allocate_shared_array_throws_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Glen Joseph Fernandes + * Copyright (c) 2012-2014 Glen Joseph Fernandes * glenfe at live dot com * * Distributed under the Boost Software License, @@ -12,15 +12,18 @@ class type { public: static unsigned int instances; + explicit type() { if (instances == 5) { throw true; } instances++; } + ~type() { instances--; } + private: type(const type&); type& operator=(const type&); @@ -36,6 +39,7 @@ int main() { } catch (...) { BOOST_TEST(type::instances == 0); } + BOOST_TEST(type::instances == 0); try { boost::allocate_shared(std::allocator(), 3); @@ -43,7 +47,7 @@ int main() { } catch (...) { BOOST_TEST(type::instances == 0); } -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + BOOST_TEST(type::instances == 0); try { boost::allocate_shared(std::allocator()); @@ -51,6 +55,7 @@ int main() { } catch (...) { BOOST_TEST(type::instances == 0); } + BOOST_TEST(type::instances == 0); try { boost::allocate_shared(std::allocator()); @@ -58,7 +63,7 @@ int main() { } catch (...) { BOOST_TEST(type::instances == 0); } -#endif + BOOST_TEST(type::instances == 0); try { boost::allocate_shared_noinit(std::allocator(), 6); @@ -66,6 +71,7 @@ int main() { } catch (...) { BOOST_TEST(type::instances == 0); } + BOOST_TEST(type::instances == 0); try { boost::allocate_shared_noinit(std::allocator(), 3); @@ -73,5 +79,24 @@ int main() { } catch (...) { BOOST_TEST(type::instances == 0); } + + BOOST_TEST(type::instances == 0); + try { + boost::allocate_shared_noinit(std::allocator()); + BOOST_ERROR("allocate_shared_noinit did not throw"); + } + catch (...) { + BOOST_TEST(type::instances == 0); + } + + BOOST_TEST(type::instances == 0); + try { + boost::allocate_shared_noinit(std::allocator()); + BOOST_ERROR("allocate_shared_noinit did not throw"); + } + catch (...) { + BOOST_TEST(type::instances == 0); + } + return boost::report_errors(); } diff --git a/test/allocate_shared_array_value_test.cpp b/test/allocate_shared_array_value_test.cpp new file mode 100644 index 0000000..c1b8b7c --- /dev/null +++ b/test/allocate_shared_array_value_test.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2012-2014 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include + +int main() { + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 4, 1); + BOOST_TEST(a1[0] == 1); + BOOST_TEST(a1[1] == 1); + BOOST_TEST(a1[2] == 1); + BOOST_TEST(a1[3] == 1); + } + + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 1); + BOOST_TEST(a1[0] == 1); + BOOST_TEST(a1[1] == 1); + BOOST_TEST(a1[2] == 1); + BOOST_TEST(a1[3] == 1); + } + + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 4, 1); + BOOST_TEST(a1[0] == 1); + BOOST_TEST(a1[1] == 1); + BOOST_TEST(a1[2] == 1); + BOOST_TEST(a1[3] == 1); + } + + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 1); + BOOST_TEST(a1[0] == 1); + BOOST_TEST(a1[1] == 1); + BOOST_TEST(a1[2] == 1); + BOOST_TEST(a1[3] == 1); + } + + return boost::report_errors(); +} diff --git a/test/allocate_shared_arrays_create_test.cpp b/test/allocate_shared_arrays_create_test.cpp deleted file mode 100644 index a7e95d7..0000000 --- a/test/allocate_shared_arrays_create_test.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2012 Glen Joseph Fernandes - * glenfe at live dot com - * - * Distributed under the Boost Software License, - * Version 1.0. (See accompanying file LICENSE_1_0.txt - * or copy at http://boost.org/LICENSE_1_0.txt) - */ -#include -#include - -class type { -public: - type(int x, int y) - : x(x), y(y) { - } - const int x; - const int y; -private: - type& operator=(const type&); -}; - -int main() { -#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), {0, 1, 2, 3}); - BOOST_TEST(a1[0] == 0); - BOOST_TEST(a1[1] == 1); - BOOST_TEST(a1[2] == 2); - BOOST_TEST(a1[3] == 3); - } - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { {0, 1}, {2, 3} }); - BOOST_TEST(a1[0][0] == 0); - BOOST_TEST(a1[0][1] == 1); - BOOST_TEST(a1[1][0] == 2); - BOOST_TEST(a1[1][1] == 3); - } - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2, {0, 1}); - BOOST_TEST(a1[0][0] == 0); - BOOST_TEST(a1[0][1] == 1); - BOOST_TEST(a1[1][0] == 0); - BOOST_TEST(a1[1][1] == 1); - } - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2, { {0, 1}, {2, 3} }); - BOOST_TEST(a1[0][0][0] == 0); - BOOST_TEST(a1[0][0][1] == 1); - BOOST_TEST(a1[1][1][0] == 2); - BOOST_TEST(a1[1][1][1] == 3); - } - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), {0, 1}); - BOOST_TEST(a1[0][0] == 0); - BOOST_TEST(a1[0][1] == 1); - BOOST_TEST(a1[1][0] == 0); - BOOST_TEST(a1[1][1] == 1); - } - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { {0, 1}, {2, 3} }); - BOOST_TEST(a1[0][0][0] == 0); - BOOST_TEST(a1[0][0][1] == 1); - BOOST_TEST(a1[1][1][0] == 2); - BOOST_TEST(a1[1][1][1] == 3); - } -#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), {0, 1, 2, 3}); - BOOST_TEST(a1[0] == 0); - BOOST_TEST(a1[1] == 1); - BOOST_TEST(a1[2] == 2); - BOOST_TEST(a1[3] == 3); - } -#endif -#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 4, {1, 2}); - BOOST_TEST(a1[0].x == 1); - BOOST_TEST(a1[1].y == 2); - BOOST_TEST(a1[2].x == 1); - BOOST_TEST(a1[3].y == 2); - } - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), {1, 2}); - BOOST_TEST(a1[0].x == 1); - BOOST_TEST(a1[1].y == 2); - BOOST_TEST(a1[2].x == 1); - BOOST_TEST(a1[3].y == 2); - } -#endif -#endif - return boost::report_errors(); -} diff --git a/test/allocate_shared_arrays_init_test.cpp b/test/allocate_shared_arrays_init_test.cpp deleted file mode 100644 index 76173fa..0000000 --- a/test/allocate_shared_arrays_init_test.cpp +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2012 Glen Joseph Fernandes - * glenfe at live dot com - * - * Distributed under the Boost Software License, - * Version 1.0. (See accompanying file LICENSE_1_0.txt - * or copy at http://boost.org/LICENSE_1_0.txt) - */ -#include -#include - -int main() { -#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) && !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { {0, 1}, {2, 3} }); - BOOST_TEST(a1[0][0] == 0); - BOOST_TEST(a1[0][1] == 1); - BOOST_TEST(a1[1][0] == 2); - BOOST_TEST(a1[1][1] == 3); - } -#endif - return boost::report_errors(); -} diff --git a/test/allocate_shared_arrays_test.cpp b/test/allocate_shared_arrays_test.cpp index c0746d3..9dfc866 100644 --- a/test/allocate_shared_arrays_test.cpp +++ b/test/allocate_shared_arrays_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Glen Joseph Fernandes + * Copyright (c) 2012-2014 Glen Joseph Fernandes * glenfe at live dot com * * Distributed under the Boost Software License, @@ -9,152 +9,40 @@ #include #include -class type { -public: - static unsigned int instances; - explicit type(int = 0, int = 0) - : member() { - instances++; - } - ~type() { - instances--; - } -private: - type(const type&); - type& operator=(const type&); - double member; -}; - -unsigned int type::instances = 0; - int main() { +#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(a1[0][0][1] == 0); - BOOST_TEST(a1[0][1][0] == 0); - BOOST_TEST(a1[1][0][0] == 0); + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2, {0, 1}); + BOOST_TEST(a1[0][0] == 0); + BOOST_TEST(a1[0][1] == 1); + BOOST_TEST(a1[1][0] == 0); + BOOST_TEST(a1[1][1] == 1); } + { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(a1[0][0][1] == 0); - BOOST_TEST(a1[0][1][0] == 0); - BOOST_TEST(a1[1][0][0] == 0); + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1 }); + BOOST_TEST(a1[0][0] == 0); + BOOST_TEST(a1[0][1] == 1); + BOOST_TEST(a1[1][0] == 0); + BOOST_TEST(a1[1][1] == 1); } - BOOST_TEST(type::instances == 0); + { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type::instances == 8); - a1.reset(); - BOOST_TEST(type::instances == 0); + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2, { 0, 1 }); + BOOST_TEST(a1[0][0] == 0); + BOOST_TEST(a1[0][1] == 1); + BOOST_TEST(a1[1][0] == 0); + BOOST_TEST(a1[1][1] == 1); } - BOOST_TEST(type::instances == 0); + { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type::instances == 8); - a1.reset(); - BOOST_TEST(type::instances == 0); - } -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2, 1, 5); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type::instances == 8); - a1.reset(); - BOOST_TEST(type::instances == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 1, 5); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type::instances == 8); - a1.reset(); - BOOST_TEST(type::instances == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2, 1, 5); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type::instances == 8); - a1.reset(); - BOOST_TEST(type::instances == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 1, 5); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type::instances == 8); - a1.reset(); - BOOST_TEST(type::instances == 0); + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), { 0, 1 }); + BOOST_TEST(a1[0][0] == 0); + BOOST_TEST(a1[0][1] == 1); + BOOST_TEST(a1[1][0] == 0); + BOOST_TEST(a1[1][1] == 1); } #endif - { - boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator(), 2); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - } - { - boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator()); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - } - { - boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator(), 2); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - } - { - boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator()); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator(), 2); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type::instances == 8); - a1.reset(); - BOOST_TEST(type::instances == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator()); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type::instances == 8); - a1.reset(); - BOOST_TEST(type::instances == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator(), 2); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type::instances == 8); - a1.reset(); - BOOST_TEST(type::instances == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::allocate_shared_noinit(std::allocator()); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type::instances == 8); - a1.reset(); - BOOST_TEST(type::instances == 0); - } + return boost::report_errors(); } diff --git a/test/make_shared_array_args_test.cpp b/test/make_shared_array_args_test.cpp deleted file mode 100644 index 8a89429..0000000 --- a/test/make_shared_array_args_test.cpp +++ /dev/null @@ -1,172 +0,0 @@ -// make_shared_array_args_test.cpp -// -// Copyright 2007-2009, 2012 Peter Dimov -// -// 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 - -#include -#include -#include -#include - -class X -{ -private: - - X( X const & ); - X & operator=( X const & ); - - void * operator new[]( std::size_t n ); - void operator delete[]( void * p ); - -public: - - static int instances; - - int v; - - explicit X( int a1 = 0, int a2 = 0, int a3 = 0, int a4 = 0, int a5 = 0, int a6 = 0, int a7 = 0, int a8 = 0, int a9 = 0 ): v( a1+a2+a3+a4+a5+a6+a7+a8+a9 ) - { - ++instances; - } - - ~X() - { - --instances; - } -}; - -int X::instances = 0; - -int main() -{ - BOOST_TEST( X::instances == 0 ); - - { - boost::shared_ptr< X[] > px = boost::make_shared< X[] >( 2 ); - - BOOST_TEST( X::instances == 2 ); - BOOST_TEST( px[0].v == 0 ); - BOOST_TEST( px[1].v == 0 ); - - px.reset(); - - BOOST_TEST( X::instances == 0 ); - } - -#if !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) - - { - boost::shared_ptr< X[] > px = boost::make_shared< X[] >( 2, 1 ); - - BOOST_TEST( X::instances == 2 ); - BOOST_TEST( px[0].v == 1 ); - BOOST_TEST( px[1].v == 1 ); - - px.reset(); - - BOOST_TEST( X::instances == 0 ); - } - - { - boost::shared_ptr< X[] > px = boost::make_shared< X[] >( 2, 1, 2 ); - - BOOST_TEST( X::instances == 2 ); - BOOST_TEST( px[0].v == 1+2 ); - BOOST_TEST( px[1].v == 1+2 ); - - px.reset(); - - BOOST_TEST( X::instances == 0 ); - } - - { - boost::shared_ptr< X[] > px = boost::make_shared< X[] >( 2, 1, 2, 3 ); - - BOOST_TEST( X::instances == 2 ); - BOOST_TEST( px[0].v == 1+2+3 ); - BOOST_TEST( px[1].v == 1+2+3 ); - - px.reset(); - - BOOST_TEST( X::instances == 0 ); - } - - { - boost::shared_ptr< X[] > px = boost::make_shared< X[] >( 2, 1, 2, 3, 4 ); - - BOOST_TEST( X::instances == 2 ); - BOOST_TEST( px[0].v == 1+2+3+4 ); - BOOST_TEST( px[1].v == 1+2+3+4 ); - - px.reset(); - - BOOST_TEST( X::instances == 0 ); - } - - { - boost::shared_ptr< X[] > px = boost::make_shared< X[] >( 2, 1, 2, 3, 4, 5 ); - - BOOST_TEST( X::instances == 2 ); - BOOST_TEST( px[0].v == 1+2+3+4+5 ); - BOOST_TEST( px[1].v == 1+2+3+4+5 ); - - px.reset(); - - BOOST_TEST( X::instances == 0 ); - } - - { - boost::shared_ptr< X[] > px = boost::make_shared< X[] >( 2, 1, 2, 3, 4, 5, 6 ); - - BOOST_TEST( X::instances == 2 ); - BOOST_TEST( px[0].v == 1+2+3+4+5+6 ); - BOOST_TEST( px[1].v == 1+2+3+4+5+6 ); - - px.reset(); - - BOOST_TEST( X::instances == 0 ); - } - - { - boost::shared_ptr< X[] > px = boost::make_shared< X[] >( 2, 1, 2, 3, 4, 5, 6, 7 ); - - BOOST_TEST( X::instances == 2 ); - BOOST_TEST( px[0].v == 1+2+3+4+5+6+7 ); - BOOST_TEST( px[1].v == 1+2+3+4+5+6+7 ); - - px.reset(); - - BOOST_TEST( X::instances == 0 ); - } - - { - boost::shared_ptr< X[] > px = boost::make_shared< X[] >( 2, 1, 2, 3, 4, 5, 6, 7, 8 ); - - BOOST_TEST( X::instances == 2 ); - BOOST_TEST( px[0].v == 1+2+3+4+5+6+7+8 ); - BOOST_TEST( px[1].v == 1+2+3+4+5+6+7+8 ); - - px.reset(); - - BOOST_TEST( X::instances == 0 ); - } - - { - boost::shared_ptr< X[] > px = boost::make_shared< X[] >( 2, 1, 2, 3, 4, 5, 6, 7, 8, 9 ); - - BOOST_TEST( X::instances == 2 ); - BOOST_TEST( px[0].v == 1+2+3+4+5+6+7+8+9 ); - BOOST_TEST( px[1].v == 1+2+3+4+5+6+7+8+9 ); - - px.reset(); - - BOOST_TEST( X::instances == 0 ); - } - -#endif - - return boost::report_errors(); -} diff --git a/test/make_shared_array_create_test.cpp b/test/make_shared_array_create_test.cpp deleted file mode 100644 index 0bdd635..0000000 --- a/test/make_shared_array_create_test.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2012 Glen Joseph Fernandes - * glenfe at live dot com - * - * Distributed under the Boost Software License, - * Version 1.0. (See accompanying file LICENSE_1_0.txt - * or copy at http://boost.org/LICENSE_1_0.txt) - */ -#include -#include - -class type { -public: - static int instances; - explicit type(int a=0, int b=0, int c=0, int d=0, int e=0, int f=0, int g=0, int h=0, int i=0) - : a(a), b(b), c(c), d(d), e(e), f(f), g(g), h(h), i(i) { - instances++; - } - ~type() { - instances--; - } - const int a; - const int b; - const int c; - const int d; - const int e; - const int f; - const int g; - const int h; - const int i; -private: - type(const type&); - type& operator=(const type&); -}; - -int type::instances = 0; - -int main() { -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::make_shared(2, 1, 2, 3, 4, 5, 6, 7, 8, 9); - BOOST_TEST(type::instances == 2); - BOOST_TEST(a1[0].a == 1); - BOOST_TEST(a1[0].d == 4); - BOOST_TEST(a1[1].f == 6); - BOOST_TEST(a1[1].i == 9); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::make_shared(1, 2, 3, 4, 5, 6, 7, 8, 9); - BOOST_TEST(type::instances == 2); - BOOST_TEST(a1[0].a == 1); - BOOST_TEST(a1[0].d == 4); - BOOST_TEST(a1[1].f == 6); - BOOST_TEST(a1[1].i == 9); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::make_shared(2, 1, 2, 3, 4, 5, 6, 7); - BOOST_TEST(type::instances == 4); - BOOST_TEST(a1[0][0].a == 1); - BOOST_TEST(a1[0][1].d == 4); - BOOST_TEST(a1[1][0].f == 6); - BOOST_TEST(a1[1][1].i == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::make_shared(1, 2, 3, 4, 5, 6, 7); - BOOST_TEST(type::instances == 4); - BOOST_TEST(a1[0][0].a == 1); - BOOST_TEST(a1[0][1].d == 4); - BOOST_TEST(a1[1][0].f == 6); - BOOST_TEST(a1[1][1].i == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::make_shared(2, 1, 2, 3, 4, 5); - BOOST_TEST(type::instances == 8); - BOOST_TEST(a1[0][0][0].a == 1); - BOOST_TEST(a1[0][1][0].c == 3); - BOOST_TEST(a1[1][0][1].e == 5); - BOOST_TEST(a1[1][1][1].i == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::make_shared(1, 2, 3, 4, 5); - BOOST_TEST(type::instances == 8); - BOOST_TEST(a1[0][0][0].a == 1); - BOOST_TEST(a1[0][1][0].c == 3); - BOOST_TEST(a1[1][0][1].e == 5); - BOOST_TEST(a1[1][1][1].i == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::make_shared(2, 1, 2, 3); - BOOST_TEST(type::instances == 16); - BOOST_TEST(a1[0][0][0][1].a == 1); - BOOST_TEST(a1[0][0][1][0].c == 3); - BOOST_TEST(a1[0][1][0][0].f == 0); - BOOST_TEST(a1[1][0][0][0].i == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::make_shared(1, 2, 3); - BOOST_TEST(type::instances == 16); - BOOST_TEST(a1[0][0][0][1].a == 1); - BOOST_TEST(a1[0][0][1][0].c == 3); - BOOST_TEST(a1[0][1][0][0].f == 0); - BOOST_TEST(a1[1][0][0][0].i == 0); - } -#endif - return boost::report_errors(); -} diff --git a/test/make_shared_array_esft_test.cpp b/test/make_shared_array_esft_test.cpp index 9d0adb1..a93f760 100644 --- a/test/make_shared_array_esft_test.cpp +++ b/test/make_shared_array_esft_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Glen Joseph Fernandes + * Copyright (c) 2012-2014 Glen Joseph Fernandes * glenfe at live dot com * * Distributed under the Boost Software License, @@ -14,12 +14,15 @@ class type : public boost::enable_shared_from_this { public: static unsigned int instances; + explicit type() { instances++; } + ~type() { instances--; } + private: type(const type&); type& operator=(const type&); @@ -38,6 +41,7 @@ int main() { BOOST_TEST(type::instances == 3); } } + BOOST_TEST(type::instances == 0); { boost::shared_ptr a1 = boost::make_shared_noinit(3); @@ -48,5 +52,6 @@ int main() { BOOST_TEST(type::instances == 3); } } + return boost::report_errors(); } diff --git a/test/make_shared_array_init_test.cpp b/test/make_shared_array_init_test.cpp deleted file mode 100644 index 11dcb1c..0000000 --- a/test/make_shared_array_init_test.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2012 Glen Joseph Fernandes - * glenfe at live dot com - * - * Distributed under the Boost Software License, - * Version 1.0. (See accompanying file LICENSE_1_0.txt - * or copy at http://boost.org/LICENSE_1_0.txt) - */ -#include -#include - -class type { -public: - type(int value) - : value(value) { - } - const int value; -private: - type& operator=(const type&); -}; - -int main() { -#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) - { - boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); - BOOST_TEST(a1[0] == 0); - BOOST_TEST(a1[1] == 1); - BOOST_TEST(a1[2] == 2); - BOOST_TEST(a1[3] == 3); - } - { - boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); - BOOST_TEST(a1[0] == 0); - BOOST_TEST(a1[1] == 1); - BOOST_TEST(a1[2] == 2); - BOOST_TEST(a1[3] == 3); - } - { - boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); - BOOST_TEST(a1[0].value == 0); - BOOST_TEST(a1[1].value == 1); - BOOST_TEST(a1[2].value == 2); - BOOST_TEST(a1[3].value == 3); - } - { - boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); - BOOST_TEST(a1[0].value == 0); - BOOST_TEST(a1[1].value == 1); - BOOST_TEST(a1[2].value == 2); - BOOST_TEST(a1[3].value == 3); - } -#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) - { - boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); - BOOST_TEST(a1[0] == 0); - BOOST_TEST(a1[1] == 1); - BOOST_TEST(a1[2] == 2); - BOOST_TEST(a1[3] == 3); - } - { - boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); - BOOST_TEST(a1[0] == 0); - BOOST_TEST(a1[1] == 1); - BOOST_TEST(a1[2] == 2); - BOOST_TEST(a1[3] == 3); - } - { - boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); - BOOST_TEST(a1[0].value == 0); - BOOST_TEST(a1[1].value == 1); - BOOST_TEST(a1[2].value == 2); - BOOST_TEST(a1[3].value == 3); - } - { - boost::shared_ptr a1 = boost::make_shared({ 0, 1, 2, 3 }); - BOOST_TEST(a1[0].value == 0); - BOOST_TEST(a1[1].value == 1); - BOOST_TEST(a1[2].value == 2); - BOOST_TEST(a1[3].value == 3); - } -#endif -#endif - return boost::report_errors(); -} diff --git a/test/make_shared_array_noinit_test.cpp b/test/make_shared_array_noinit_test.cpp new file mode 100644 index 0000000..98bd450 --- /dev/null +++ b/test/make_shared_array_noinit_test.cpp @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2012-2014 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include +#include +#include + +class type { +public: + static unsigned int instances; + + explicit type() { + instances++; + } + + ~type() { + instances--; + } + +private: + type(const type&); + type& operator=(const type&); +}; + +unsigned int type::instances = 0; + +int main() { + { + boost::shared_ptr a1 = boost::make_shared_noinit(3); + int* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + } + + { + boost::shared_ptr a1 = boost::make_shared_noinit(); + int* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + } + + { + boost::shared_ptr a1 = boost::make_shared_noinit(2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + } + + { + boost::shared_ptr a1 = boost::make_shared_noinit(); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + } + + { + boost::shared_ptr a1 = boost::make_shared_noinit(3); + const int* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + } + + { + boost::shared_ptr a1 = boost::make_shared_noinit(); + const int* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + } + + { + boost::shared_ptr a1 = boost::make_shared_noinit(2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + } + + { + boost::shared_ptr a1 = boost::make_shared_noinit(); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + } + + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared_noinit(3); + type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + boost::weak_ptr w1 = a1; + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared_noinit(); + type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + boost::weak_ptr w1 = a1; + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared_noinit(2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 4); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared_noinit(); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 4); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared_noinit(3); + const type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared_noinit(); + const type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared_noinit(2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 4); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared_noinit(); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 4); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + return boost::report_errors(); +} diff --git a/test/make_shared_array_test.cpp b/test/make_shared_array_test.cpp index 8193553..ebb76c7 100644 --- a/test/make_shared_array_test.cpp +++ b/test/make_shared_array_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Glen Joseph Fernandes + * Copyright (c) 2012-2014 Glen Joseph Fernandes * glenfe at live dot com * * Distributed under the Boost Software License, @@ -14,17 +14,18 @@ class type { public: static unsigned int instances; - explicit type(int = 0, int = 0) - : member() { + + explicit type() { instances++; } + ~type() { instances--; } + private: type(const type&); type& operator=(const type&); - double member; }; unsigned int type::instances = 0; @@ -40,6 +41,38 @@ int main() { BOOST_TEST(a1[1] == 0); BOOST_TEST(a1[2] == 0); } + + { + boost::shared_ptr a1 = boost::make_shared(); + int* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 0); + BOOST_TEST(a1[2] == 0); + } + + { + boost::shared_ptr a1 = boost::make_shared(2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a1[0][0] == 0); + BOOST_TEST(a1[0][1] == 0); + BOOST_TEST(a1[1][0] == 0); + BOOST_TEST(a1[1][1] == 0); + } + + { + boost::shared_ptr a1 = boost::make_shared(); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a1[0][0] == 0); + BOOST_TEST(a1[0][1] == 0); + BOOST_TEST(a1[1][0] == 0); + BOOST_TEST(a1[1][1] == 0); + } + { boost::shared_ptr a1 = boost::make_shared(3); const int* a2 = a1.get(); @@ -50,6 +83,38 @@ int main() { BOOST_TEST(a1[1] == 0); BOOST_TEST(a1[2] == 0); } + + { + boost::shared_ptr a1 = boost::make_shared(); + const int* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 0); + BOOST_TEST(a1[2] == 0); + } + + { + boost::shared_ptr a1 = boost::make_shared(2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a1[0][0] == 0); + BOOST_TEST(a1[0][1] == 0); + BOOST_TEST(a1[1][0] == 0); + BOOST_TEST(a1[1][1] == 0); + } + + { + boost::shared_ptr a1 = boost::make_shared(); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a1[0][0] == 0); + BOOST_TEST(a1[0][1] == 0); + BOOST_TEST(a1[1][0] == 0); + BOOST_TEST(a1[1][1] == 0); + } + BOOST_TEST(type::instances == 0); { boost::shared_ptr a1 = boost::make_shared(3); @@ -62,6 +127,40 @@ int main() { a1.reset(); BOOST_TEST(type::instances == 0); } + + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared(); + type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + boost::weak_ptr w1 = a1; + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared(2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 4); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared(); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 4); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); { boost::shared_ptr a1 = boost::make_shared(3); @@ -73,109 +172,10 @@ int main() { a1.reset(); BOOST_TEST(type::instances == 0); } -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + BOOST_TEST(type::instances == 0); { - boost::shared_ptr a1 = boost::make_shared(3, 1, 5); - type* a2 = a1.get(); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(a2 != 0); - BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); - BOOST_TEST(type::instances == 3); - boost::weak_ptr w1 = a1; - a1.reset(); - BOOST_TEST(type::instances == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::make_shared(1, 5); - type* a2 = a1.get(); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(a2 != 0); - BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); - BOOST_TEST(type::instances == 3); - boost::weak_ptr w1 = a1; - a1.reset(); - BOOST_TEST(type::instances == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::make_shared(3, 1, 5); - const type* a2 = a1.get(); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(a2 != 0); - BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); - BOOST_TEST(type::instances == 3); - a1.reset(); - BOOST_TEST(type::instances == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::make_shared(1, 5); - const type* a2 = a1.get(); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(a2 != 0); - BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); - BOOST_TEST(type::instances == 3); - a1.reset(); - BOOST_TEST(type::instances == 0); - } -#endif - { - boost::shared_ptr a1 = boost::make_shared_noinit(3); - int* a2 = a1.get(); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(a2 != 0); - BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); - } - { - boost::shared_ptr a1 = boost::make_shared_noinit(); - int* a2 = a1.get(); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(a2 != 0); - BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); - } - { - boost::shared_ptr a1 = boost::make_shared_noinit(3); - const int* a2 = a1.get(); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(a2 != 0); - BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); - } - { - boost::shared_ptr a1 = boost::make_shared_noinit(); - const int* a2 = a1.get(); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(a2 != 0); - BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::make_shared_noinit(3); - type* a2 = a1.get(); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(a2 != 0); - BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); - BOOST_TEST(type::instances == 3); - boost::weak_ptr w1 = a1; - a1.reset(); - BOOST_TEST(type::instances == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::make_shared_noinit(); - type* a2 = a1.get(); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(a2 != 0); - BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); - BOOST_TEST(type::instances == 3); - boost::weak_ptr w1 = a1; - a1.reset(); - BOOST_TEST(type::instances == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::make_shared_noinit(3); + boost::shared_ptr a1 = boost::make_shared(); const type* a2 = a1.get(); BOOST_TEST(a1.use_count() == 1); BOOST_TEST(a2 != 0); @@ -184,16 +184,26 @@ int main() { a1.reset(); BOOST_TEST(type::instances == 0); } + BOOST_TEST(type::instances == 0); { - boost::shared_ptr a1 = boost::make_shared_noinit(); - const type* a2 = a1.get(); + boost::shared_ptr a1 = boost::make_shared(2); + BOOST_TEST(a1.get() != 0); BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(a2 != 0); - BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); - BOOST_TEST(type::instances == 3); + BOOST_TEST(type::instances == 4); a1.reset(); BOOST_TEST(type::instances == 0); } + + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared(); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 4); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + return boost::report_errors(); } diff --git a/test/make_shared_array_throws_test.cpp b/test/make_shared_array_throws_test.cpp index 69e9b88..98d6ea7 100644 --- a/test/make_shared_array_throws_test.cpp +++ b/test/make_shared_array_throws_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Glen Joseph Fernandes + * Copyright (c) 2012-2014 Glen Joseph Fernandes * glenfe at live dot com * * Distributed under the Boost Software License, @@ -12,15 +12,18 @@ class type { public: static unsigned int instances; + explicit type() { if (instances == 5) { throw true; } instances++; } + ~type() { instances--; } + private: type(const type&); type& operator=(const type&); @@ -36,6 +39,7 @@ int main() { } catch (...) { BOOST_TEST(type::instances == 0); } + BOOST_TEST(type::instances == 0); try { boost::make_shared(3); @@ -43,7 +47,7 @@ int main() { } catch (...) { BOOST_TEST(type::instances == 0); } -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + BOOST_TEST(type::instances == 0); try { boost::make_shared(); @@ -51,6 +55,7 @@ int main() { } catch (...) { BOOST_TEST(type::instances == 0); } + BOOST_TEST(type::instances == 0); try { boost::make_shared(); @@ -58,7 +63,7 @@ int main() { } catch (...) { BOOST_TEST(type::instances == 0); } -#endif + BOOST_TEST(type::instances == 0); try { boost::make_shared_noinit(6); @@ -66,6 +71,7 @@ int main() { } catch (...) { BOOST_TEST(type::instances == 0); } + BOOST_TEST(type::instances == 0); try { boost::make_shared_noinit(3); @@ -73,5 +79,24 @@ int main() { } catch (...) { BOOST_TEST(type::instances == 0); } + + BOOST_TEST(type::instances == 0); + try { + boost::make_shared_noinit(); + BOOST_ERROR("make_shared_noinit did not throw"); + } + catch (...) { + BOOST_TEST(type::instances == 0); + } + + BOOST_TEST(type::instances == 0); + try { + boost::make_shared_noinit(); + BOOST_ERROR("make_shared_noinit did not throw"); + } + catch (...) { + BOOST_TEST(type::instances == 0); + } + return boost::report_errors(); } diff --git a/test/make_shared_array_value_test.cpp b/test/make_shared_array_value_test.cpp new file mode 100644 index 0000000..f042ede --- /dev/null +++ b/test/make_shared_array_value_test.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2012-2014 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include + +int main() { + { + boost::shared_ptr a1 = boost::make_shared(4, 1); + BOOST_TEST(a1[0] == 1); + BOOST_TEST(a1[1] == 1); + BOOST_TEST(a1[2] == 1); + BOOST_TEST(a1[3] == 1); + } + + { + boost::shared_ptr a1 = boost::make_shared(1); + BOOST_TEST(a1[0] == 1); + BOOST_TEST(a1[1] == 1); + BOOST_TEST(a1[2] == 1); + BOOST_TEST(a1[3] == 1); + } + + { + boost::shared_ptr a1 = boost::make_shared(4, 1); + BOOST_TEST(a1[0] == 1); + BOOST_TEST(a1[1] == 1); + BOOST_TEST(a1[2] == 1); + BOOST_TEST(a1[3] == 1); + } + + { + boost::shared_ptr a1 = boost::make_shared(1); + BOOST_TEST(a1[0] == 1); + BOOST_TEST(a1[1] == 1); + BOOST_TEST(a1[2] == 1); + BOOST_TEST(a1[3] == 1); + } + + return boost::report_errors(); +} diff --git a/test/make_shared_arrays_create_test.cpp b/test/make_shared_arrays_create_test.cpp deleted file mode 100644 index c6a1b4f..0000000 --- a/test/make_shared_arrays_create_test.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2012 Glen Joseph Fernandes - * glenfe at live dot com - * - * Distributed under the Boost Software License, - * Version 1.0. (See accompanying file LICENSE_1_0.txt - * or copy at http://boost.org/LICENSE_1_0.txt) - */ -#include -#include - -class type { -public: - type(int x, int y) - : x(x), y(y) { - } - const int x; - const int y; -private: - type& operator=(const type&); -}; - -int main() { -#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) - { - boost::shared_ptr a1 = boost::make_shared({0, 1, 2, 3}); - BOOST_TEST(a1[0] == 0); - BOOST_TEST(a1[1] == 1); - BOOST_TEST(a1[2] == 2); - BOOST_TEST(a1[3] == 3); - } - { - boost::shared_ptr a1 = boost::make_shared({ {0, 1}, {2, 3} }); - BOOST_TEST(a1[0][0] == 0); - BOOST_TEST(a1[0][1] == 1); - BOOST_TEST(a1[1][0] == 2); - BOOST_TEST(a1[1][1] == 3); - } - { - boost::shared_ptr a1 = boost::make_shared(2, {0, 1}); - BOOST_TEST(a1[0][0] == 0); - BOOST_TEST(a1[0][1] == 1); - BOOST_TEST(a1[1][0] == 0); - BOOST_TEST(a1[1][1] == 1); - } - { - boost::shared_ptr a1 = boost::make_shared(2, { {0, 1}, {2, 3} }); - BOOST_TEST(a1[0][0][0] == 0); - BOOST_TEST(a1[0][0][1] == 1); - BOOST_TEST(a1[1][1][0] == 2); - BOOST_TEST(a1[1][1][1] == 3); - } - { - boost::shared_ptr a1 = boost::make_shared({ 0, 1 }); - BOOST_TEST(a1[0][0] == 0); - BOOST_TEST(a1[0][1] == 1); - BOOST_TEST(a1[1][0] == 0); - BOOST_TEST(a1[1][1] == 1); - } - { - boost::shared_ptr a1 = boost::make_shared({ {0, 1}, {2, 3} }); - BOOST_TEST(a1[0][0][0] == 0); - BOOST_TEST(a1[0][0][1] == 1); - BOOST_TEST(a1[1][1][0] == 2); - BOOST_TEST(a1[1][1][1] == 3); - } -#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) - { - boost::shared_ptr a1 = boost::make_shared({0, 1, 2, 3}); - BOOST_TEST(a1[0] == 0); - BOOST_TEST(a1[1] == 1); - BOOST_TEST(a1[2] == 2); - BOOST_TEST(a1[3] == 3); - } -#endif -#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - { - boost::shared_ptr a1 = boost::make_shared(4, {1, 2}); - BOOST_TEST(a1[0].x == 1); - BOOST_TEST(a1[1].y == 2); - BOOST_TEST(a1[2].x == 1); - BOOST_TEST(a1[3].y == 2); - } - { - boost::shared_ptr a1 = boost::make_shared({1, 2}); - BOOST_TEST(a1[0].x == 1); - BOOST_TEST(a1[1].y == 2); - BOOST_TEST(a1[2].x == 1); - BOOST_TEST(a1[3].y == 2); - } -#endif -#endif - return boost::report_errors(); -} diff --git a/test/make_shared_arrays_init_test.cpp b/test/make_shared_arrays_init_test.cpp deleted file mode 100644 index 1646d5a..0000000 --- a/test/make_shared_arrays_init_test.cpp +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2012 Glen Joseph Fernandes - * glenfe at live dot com - * - * Distributed under the Boost Software License, - * Version 1.0. (See accompanying file LICENSE_1_0.txt - * or copy at http://boost.org/LICENSE_1_0.txt) - */ -#include -#include - -int main() { -#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) && !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) - { - boost::shared_ptr a1 = boost::make_shared({ {0, 1}, {2, 3} }); - BOOST_TEST(a1[0][0] == 0); - BOOST_TEST(a1[0][1] == 1); - BOOST_TEST(a1[1][0] == 2); - BOOST_TEST(a1[1][1] == 3); - } -#endif - return boost::report_errors(); -} diff --git a/test/make_shared_arrays_test.cpp b/test/make_shared_arrays_test.cpp index e03a13c..b905a83 100644 --- a/test/make_shared_arrays_test.cpp +++ b/test/make_shared_arrays_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Glen Joseph Fernandes + * Copyright (c) 2012-2014 Glen Joseph Fernandes * glenfe at live dot com * * Distributed under the Boost Software License, @@ -9,152 +9,40 @@ #include #include -class type { -public: - static unsigned int instances; - explicit type(int = 0, int = 0) - : member() { - instances++; - } - ~type() { - instances--; - } -private: - type(const type&); - type& operator=(const type&); - double member; -}; - -unsigned int type::instances = 0; - int main() { +#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) { - boost::shared_ptr a1 = boost::make_shared(2); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(a1[0][0][1] == 0); - BOOST_TEST(a1[0][1][0] == 0); - BOOST_TEST(a1[1][0][0] == 0); - } - { - boost::shared_ptr a1 = boost::make_shared(2); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(a1[0][0][1] == 0); - BOOST_TEST(a1[0][1][0] == 0); - BOOST_TEST(a1[1][0][0] == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::make_shared(2); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type::instances == 8); - a1.reset(); - BOOST_TEST(type::instances == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::make_shared(2); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type::instances == 8); - a1.reset(); - BOOST_TEST(type::instances == 0); + boost::shared_ptr a1 = boost::make_shared(2, {0, 1}); + BOOST_TEST(a1[0][0] == 0); + BOOST_TEST(a1[0][1] == 1); + BOOST_TEST(a1[1][0] == 0); + BOOST_TEST(a1[1][1] == 1); } -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - BOOST_TEST(type::instances == 0); + { - boost::shared_ptr a1 = boost::make_shared(2, 1, 5); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type::instances == 8); - a1.reset(); - BOOST_TEST(type::instances == 0); + boost::shared_ptr a1 = boost::make_shared({ 0, 1 }); + BOOST_TEST(a1[0][0] == 0); + BOOST_TEST(a1[0][1] == 1); + BOOST_TEST(a1[1][0] == 0); + BOOST_TEST(a1[1][1] == 1); } - BOOST_TEST(type::instances == 0); + { - boost::shared_ptr a1 = boost::make_shared(1, 5); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type::instances == 8); - a1.reset(); - BOOST_TEST(type::instances == 0); + boost::shared_ptr a1 = boost::make_shared(2, { 0, 1 }); + BOOST_TEST(a1[0][0] == 0); + BOOST_TEST(a1[0][1] == 1); + BOOST_TEST(a1[1][0] == 0); + BOOST_TEST(a1[1][1] == 1); } - BOOST_TEST(type::instances == 0); + { - boost::shared_ptr a1 = boost::make_shared(2, 1, 5); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type::instances == 8); - a1.reset(); - BOOST_TEST(type::instances == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::make_shared(1, 5); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type::instances == 8); - a1.reset(); - BOOST_TEST(type::instances == 0); + boost::shared_ptr a1 = boost::make_shared({ 0, 1 }); + BOOST_TEST(a1[0][0] == 0); + BOOST_TEST(a1[0][1] == 1); + BOOST_TEST(a1[1][0] == 0); + BOOST_TEST(a1[1][1] == 1); } #endif - { - boost::shared_ptr a1 = boost::make_shared_noinit(2); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - } - { - boost::shared_ptr a1 = boost::make_shared_noinit(); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - } - { - boost::shared_ptr a1 = boost::make_shared_noinit(2); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - } - { - boost::shared_ptr a1 = boost::make_shared_noinit(); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::make_shared_noinit(2); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type::instances == 8); - a1.reset(); - BOOST_TEST(type::instances == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::make_shared_noinit(); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type::instances == 8); - a1.reset(); - BOOST_TEST(type::instances == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::make_shared_noinit(2); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type::instances == 8); - a1.reset(); - BOOST_TEST(type::instances == 0); - } - BOOST_TEST(type::instances == 0); - { - boost::shared_ptr a1 = boost::make_shared_noinit(); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type::instances == 8); - a1.reset(); - BOOST_TEST(type::instances == 0); - } + return boost::report_errors(); } From db78d9b2be694d85e3a85f413242c9dfd3392aa4 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Thu, 23 Jan 2014 21:16:51 -0800 Subject: [PATCH 12/39] Update make_shared for arrays documentation --- make_shared_array.html | 254 +++++++++++++---------------------------- 1 file changed, 81 insertions(+), 173 deletions(-) diff --git a/make_shared_array.html b/make_shared_array.html index 3437e9e..6959ca1 100644 --- a/make_shared_array.html +++ b/make_shared_array.html @@ -5,7 +5,7 @@ -

boost.png (6897 bytes)boost.png (6897 bytes)make_shared and allocate_shared for arrays

Introduction
@@ -29,103 +29,69 @@ allowing finer control.

Synopsis

namespace boost {
-    template<typename U> // U = T[]
+    template<typename U> // U is T[]
     shared_ptr<U> make_shared(size_t size);
 
-    template<typename U, typename A> // U = T[]
+    template<typename U, typename A> // U is T[]
     shared_ptr<U> allocate_shared(const A& allocator, size_t size);
+    
+    template<typename U> // U is T[N]
+    shared_ptr<U> make_shared();
 
-#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)   
-    template<typename U, typename... Args> // U = T[]
-    shared_ptr<U> make_shared(size_t size, Args&&... args);
+    template<typename U, typename A> // U is T[N]
+    shared_ptr<U> allocate_shared(const A& allocator);
+   
+    template<typename U> // U is T[]
+    shared_ptr<U> make_shared(size_t size, const T& value);
 
-    template<typename U, typename... Args> // U = T[N]
-    shared_ptr<U> make_shared(Args&&... args);
+    template<typename U, typename A> // U is T[]
+    shared_ptr<U> allocate_shared(const A& allocator, size_t size, const T& value);
 
-    template<typename U, typename A, typename... Args> // U = T[]
-    shared_ptr<U> allocate_shared(const A& allocator, size_t size, Args&&... args);
+    template<typename U> // U is T[N]
+    shared_ptr<U> make_shared(const T& value);
 
-    template<typename U, typename A, typename... Args> // U = T[N]
-    shared_ptr<U> allocate_shared(const A& allocator, Args&&... args);
-#endif
+    template<typename U, typename A> // U is T[N]
+    shared_ptr<U> allocate_shared(const A& allocator, const T& value);
 
-#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)    
-    template<typename U, typename... Args> // U = T[N]
-    shared_ptr<U> make_shared(const T (&list)[N]);
-
-    template<typename U, typename... Args> // U = T[][N]
-    shared_ptr<U> make_shared(size_t size, const T (&list)[N]);
-
-    template<typename U, typename... Args> // U = T[M][N]
-    shared_ptr<U> make_shared(const T (&list)[N]);
-
-    template<typename U, typename A, typename... Args> // U = T[N]
-    shared_ptr<T[> allocate_shared(const A& allocator, const T (&list)[N]);
-
-    template<typename U, typename A, typename... Args> // U = T[][N]
-    shared_ptr<U> allocate_shared(const A& allocator, size_t size, const T (&list)[N]);
-
-    template<typename U, typename A, typename... Args> // U = T[M][N]
-    shared_ptr<U> allocate_shared(const A& allocator, const T (&list)[N]);
-
-#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
-    template<typename U, typename... Args> // U = T[]
-    shared_ptr<U> make_shared(initializer_list<T> list);
-
-    template<typename U, typename A, typename... Args> // U = T[]
-    shared_ptr<U> allocate_shared(const A& allocator, initializer_list<T> list);
-#endif
-
-#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)    
-    template<typename U> // U = T[]
-    shared_ptr<U> make_shared(size_t size, T&& value);
-
-    template<typename U> // U = T[N]
-    shared_ptr<U> make_shared(T&& value);
-
-    template<typename U, typename A> // U = T[]
-    shared_ptr<U> allocate_shared(const A& allocator, size_t size, T&& value);
-
-    template<typename U, typename A> // U = T[N]
-    shared_ptr<U> allocate_shared(const A& allocator, T&& value);
-#endif
-#endif
-
-    template<typename U> // U = T[]
+    template<typename U> // U is T[]
     shared_ptr<U> make_shared_noinit(size_t size);
 
-    template<typename U> // U = T[N]
-    shared_ptr<U> make_shared_noinit();
-
-    template<typename U, typename A> // U = T[]
+    template<typename U, typename A> // U is T[]
     shared_ptr<U> allocate_shared_noinit(const A& allocator, size_t size);
 
-    template<typename U, typename A> // U = T[N]
+    template<typename U> // U is T[N]
+    shared_ptr<U> make_shared_noinit();
+
+    template<typename U, typename A> // U is T[N]
     shared_ptr<U> allocate_shared_noinit(const A& allocator);
 }

Free Functions

-
template<typename U, typename... Args> // U = T[]
-shared_ptr<U> make_shared(size_t size, Args&&... args);
+    
template<typename U> // U is T[]
+shared_ptr<U> make_shared(size_t size);
 
-template<typename U, typename A, typename... Args> // U = T[]
-shared_ptr<U> allocate_shared(const A& allocator, size_t size, Args&&... args);
+template<typename U, typename A> // U is T[] +shared_ptr<U> allocate_shared(const A& allocator, size_t size); + +template<typename U> // U is T[N] +shared_ptr<U> make_shared(); + +template<typename U, typename A> // U is T[N] +shared_ptr<U> allocate_shared(const A& allocator);

Requires: The expression - new(pointer) T(forward<Args>(args)...), where - pointer is a void* pointing to storage - suitable to hold an object of type T, shall be - well-formed. A shall be an Allocator, as - described in section 20.1.5 (Allocator requirements) - of the C++ Standard. The copy constructor and destructor of - A shall not throw.

+ new(pointer) T(), where pointer is a + void* pointing to storage suitable to hold an object + of type T, shall be well-formed. A + shall be an Allocator, as described in section 20.1.5 + (Allocator requirements) of the C++ Standard. + The copy constructor and destructor of A shall not + throw.

Effects: Allocates memory suitable for an array of type T and size size and constructs an array of objects in it via the placement new expression - new(pointer) T() or - new(pointer) T(args...). - allocate_shared uses a copy of - allocator to allocate memory. If an exception is thrown, - has no effect.

+ new(pointer) T(). allocate_shared uses + a copy of allocator to allocate memory. If an + exception is thrown, has no effect.

Returns: A shared_ptr instance that stores and owns the address of the newly constructed array of type T and size size.

@@ -137,121 +103,63 @@ shared_ptr<U> allocate_shared(const A& allocator, size_t size, Args&am the returned shared_ptr and an array of type T of size size in a single allocation. This provides efficiency to equivalent to an intrusive smart array - pointer.

-

The prototypes shown above are used if your compiler supports r-value - references and variadic templates. They perfectly forward the - args parameters to the constructors of - T for each array element.

-

Otherwise, you can use the overloads which take only the array size - (and the allocator in case of allocate_shared) and do not - take any constructor arguments. These overloads invoke the default - constructor of T for each array element.

+ pointer.

-
template<typename U, typename... Args> // U = T[N]
-shared_ptr<U> make_shared(Args&&... args);
+    
template<typename U> // U is T[]
+shared_ptr<U> make_shared(size_t size, const T& value);
 
-template<typename U, typename A, typename... Args> // U = T[N]
-shared_ptr<U> allocate_shared(const A& allocator, Args&&... args);
-
-

Description: These overloads of the utilities above are for a - fixed size array.

-
-
template<typename U, typename... Args> // U = T[]
-shared_ptr<U> make_shared(initializer_list<T> list);
+template<typename U, typename A> // U is T[]
+shared_ptr<U> allocate_shared(const A& allocator, size_t size, const T& value);
 
-template<typename U, typename A, typename... Args> // U = T[]
-shared_ptr<U> allocate_shared(const A& allocator, initializer_list<T> list);
-
-

Description: These overloads initialize the array elements - from the initializer list.

-
-
template<typename U, typename... Args> // U = T[N]
-shared_ptr<U> make_shared(const T (&list)[N]);
+template<typename U> // U is T[N]
+shared_ptr<U> make_shared(const T& value);
 
-template<typename U, typename A, typename... Args> // U = T[N]
-shared_ptr<U> allocate_shared(const A& allocator, const T (&list)[N]);
-
-

Description: These overloads of the utilities above are for a - fixed size array.

-
-
template<typename U, typename... Args> // U = T[][N]
-shared_ptr<U> make_shared(size_t size, const T (&list)[N]);
-
-template<typename U, typename A, typename... Args> // U = T[][N]
-shared_ptr<U> allocate_shared(const A& allocator, size_t size, const T (&list)[N]);
-
-

Description: These overloads initialize inner array elements - from the initializer list.

-
-
template<typename U, typename... Args> // U = T[M][N]
-shared_ptr<U> make_shared(const T (&list)[N]);
-
-template<typename U, typename A, typename... Args> // U = T[M][N]
-shared_ptr<U> allocate_shared(const A& allocator, const T (&list)[N]);
-
-

Description: These overloads of the utilities above are for a - fixed size array.

-
-
template<typename U> // U = T[]
-shared_ptr<U> make_shared(size_t size, T&& value);
-
-template<typename U, typename A> // U = T[]
-shared_ptr<U> allocate_shared(const A& allocator, size_t size, T&& value);
+template<typename U, typename A> // U is T[N] +shared_ptr<U> allocate_shared(const A& allocator, const T& value);

Description: These overloads initialize array elements with the given value.

-
template<typename U> // U = T[N]
-shared_ptr<U> make_shared(T&& value);
-
-template<typename U, typename A> // U = T[N]
-shared_ptr<U> allocate_shared(const A& allocator, T&& value);
-
-

Description: These overloads of the utilities above are for a - fixed size array.

-
-
template<typename U> // U = T[]
+    
template<typename U> // U is T[]
 shared_ptr<U> make_shared_noinit(size_t size);
 
-template<typename U, typename A> // U = T[]
-shared_ptr<U> allocate_shared_noinit(const A& allocator, size_t size);
+template<typename U, typename A> // U is T[] +shared_ptr<U> allocate_shared_noinit(const A& allocator, size_t size); + +template<typename U> // U is T[N] +shared_ptr<U> make_shared_noinit(); + +template<typename U, typename A> // U is T[N] +shared_ptr<U> allocate_shared_noinit(const A& allocator);

Description: These overloads do not perform any value initialization of elements.

-
-
template<typename U> // U = T[N]
-shared_ptr<U> make_shared_noinit();
-
-template<typename U, typename A> // U = T[N]
-shared_ptr<U> allocate_shared_noinit(const A& allocator);
-
-

Description: These overloads of the utilities above are for a - fixed size array.

-
-

Example

-

An example of each overload of make_shared for arrays:

+
+

Examples

+

Some examples of each overload of make_shared for arrays:

boost::shared_ptr<int[]> a1 = boost::make_shared<int[]>(size);
-boost::shared_ptr<point[]> a2 = boost::make_shared<point[]>(size, x, y);
-boost::shared_ptr<point[5]> a3 = boost::make_shared<point[5]>(x, y);
-boost::shared_ptr<int[]> a4 = boost::make_shared<int[]>({1, 2, 3});
-boost::shared_ptr<int[3]> a5 = boost::make_shared<int[3]>({1, 2, 3});
-boost::shared_ptr<int[][3]> a6 = boost::make_shared<int[][3]>(size, {1, 2, 3});
-boost::shared_ptr<int[5][3]> a7 = boost::make_shared<int[5][3]>({1, 2, 3});
-boost::shared_ptr<point[]> a8 = boost::make_shared<point[]>(size, {x, y});
-boost::shared_ptr<point[5]> a9 = boost::make_shared<point[5]>({x, y});
-boost::shared_ptr<int[]> a10 = boost::make_shared_noinit<int[]>(size);
-boost::shared_ptr<int[5]> a11 = boost::make_shared_noinit<int[5]>();
+boost::shared_ptr<int[8]> a2 = boost::make_shared<int[8]>(); +boost::shared_ptr<int[][2]> a3 = boost::make_shared<int[][2]>(size); +boost::shared_ptr<int[4][2]> a4 = boost::make_shared<int[4][2]>(); +boost::shared_ptr<int[]> a5 = boost::make_shared<int[]>(size, 1); +boost::shared_ptr<int[8]> a6 = boost::make_shared<int[8]>(1); +boost::shared_ptr<int[][2]> a7 = boost::make_shared<int[][2]>(size, {1, 2}); +boost::shared_ptr<int[4][2]> a8 = boost::make_shared<int[4][2]>({1, 2}); +boost::shared_ptr<int[]> a9 = boost::make_shared_noinit<int[]>(size); +boost::shared_ptr<int[8]> a10 = boost::make_shared_noinit<int[8]>(); +boost::shared_ptr<int[][2]> a11 = boost::make_shared_noinit<int[][2]>(size); +boost::shared_ptr<int[4][2]> a12 = boost::make_shared_noinit<int[4][2]>();

History

November 2012. Glen Fernandes contributed implementations of make_shared and allocate_shared for arrays.


-

$Date: 2012-10-30 10:12:25 -0800 (Tue, 30 Oct 2012) $

-

Copyright 2012 Glen Fernandes. 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.

+

$Date: 2014-01-20 11:10:00 -0800 (Mon, 20 Jan 2014) $

+

Copyright 2012-2014 Glen Fernandes. 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.

From 87e5debdc24ac6edf09e32a71c914fa8a9fe3605 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Tue, 28 Jan 2014 02:27:49 -0800 Subject: [PATCH 13/39] Minor cosmetic changes in make_shared for arrays --- .../boost/smart_ptr/allocate_shared_array.hpp | 74 ++++++++++--------- .../boost/smart_ptr/detail/array_deleter.hpp | 11 +-- .../boost/smart_ptr/detail/array_traits.hpp | 4 +- .../boost/smart_ptr/detail/array_utility.hpp | 21 ++++-- include/boost/smart_ptr/make_shared_array.hpp | 70 +++++++++--------- test/allocate_shared_array_test.cpp | 2 +- test/allocate_shared_array_throws_test.cpp | 6 +- test/make_shared_array_throws_test.cpp | 6 +- 8 files changed, 103 insertions(+), 91 deletions(-) diff --git a/include/boost/smart_ptr/allocate_shared_array.hpp b/include/boost/smart_ptr/allocate_shared_array.hpp index b76e912..905d311 100644 --- a/include/boost/smart_ptr/allocate_shared_array.hpp +++ b/include/boost/smart_ptr/allocate_shared_array.hpp @@ -9,11 +9,11 @@ #ifndef BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP #define BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP -#include #include #include #include #include +#include namespace boost { template @@ -21,13 +21,14 @@ namespace boost { allocate_shared(const A& allocator, std::size_t size) { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; + typedef typename boost::remove_cv::type T3; T1* p1 = 0; - T2* p2 = 0; + T3* p2 = 0; std::size_t n1 = size * boost::detail::array_total::size; - boost::detail::allocate_array_helper a1(allocator, n1, &p2); - boost::detail::array_deleter d1(n1); + boost::detail::allocate_array_helper a1(allocator, n1, &p2); + boost::detail::array_deleter d1(n1); boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; + typedef boost::detail::array_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); d2->init(p2); @@ -39,15 +40,16 @@ namespace boost { allocate_shared(const A& allocator) { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; + typedef typename boost::remove_cv::type T3; enum { N = boost::detail::array_total::size }; T1* p1 = 0; - T2* p2 = 0; - boost::detail::allocate_array_helper a1(allocator, &p2); - boost::detail::array_deleter d1; + T3* p2 = 0; + boost::detail::allocate_array_helper a1(allocator, &p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; + typedef boost::detail::array_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); d2->init(p2); @@ -57,22 +59,22 @@ namespace boost { template inline typename boost::detail::sp_if_array::type allocate_shared(const A& allocator, std::size_t size, - const typename boost::detail::array_inner::type& list) { + const typename boost::detail::array_inner::type& value) { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; - typedef const T2 T3; + typedef typename boost::remove_cv::type T3; + typedef const T2 T4; enum { M = boost::detail::array_total::size }; T1* p1 = 0; - T2* p2 = 0; - T3* p3 = 0; + T3* p2 = 0; + T4* p3 = reinterpret_cast(&value); std::size_t n1 = M * size; - boost::detail::allocate_array_helper a1(allocator, n1, &p2); - boost::detail::array_deleter d1(n1); + boost::detail::allocate_array_helper a1(allocator, n1, &p2); + boost::detail::array_deleter d1(n1); boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; - p3 = reinterpret_cast(&list); + typedef boost::detail::array_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); d2->template init(p2, p3); @@ -81,23 +83,23 @@ namespace boost { template inline typename boost::detail::sp_if_size_array::type - allocate_shared(const A& allocator, - const typename boost::detail::array_inner::type& list) { + allocate_shared(const A& allocator, + const typename boost::detail::array_inner::type& value) { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; - typedef const T2 T3; + typedef typename boost::remove_cv::type T3; + typedef const T2 T4; enum { M = boost::detail::array_total::size, - N = boost::detail::array_total::size + N = boost::detail::array_total::size }; T1* p1 = 0; - T2* p2 = 0; - T3* p3 = 0; - boost::detail::allocate_array_helper a1(allocator, &p2); - boost::detail::array_deleter d1; + T3* p2 = 0; + T4* p3 = reinterpret_cast(&value); + boost::detail::allocate_array_helper a1(allocator, &p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; - p3 = reinterpret_cast(&list); + typedef boost::detail::array_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); d2->template init(p2, p3); @@ -109,13 +111,14 @@ namespace boost { allocate_shared_noinit(const A& allocator, std::size_t size) { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; + typedef typename boost::remove_cv::type T3; T1* p1 = 0; - T2* p2 = 0; + T3* p2 = 0; std::size_t n1 = size * boost::detail::array_total::size; - boost::detail::allocate_array_helper a1(allocator, n1, &p2); - boost::detail::array_deleter d1(n1); + boost::detail::allocate_array_helper a1(allocator, n1, &p2); + boost::detail::array_deleter d1(n1); boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; + typedef boost::detail::array_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); d2->noinit(p2); @@ -127,15 +130,16 @@ namespace boost { allocate_shared_noinit(const A& allocator) { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; + typedef typename boost::remove_cv::type T3; enum { N = boost::detail::array_total::size }; T1* p1 = 0; - T2* p2 = 0; - boost::detail::allocate_array_helper a1(allocator, &p2); - boost::detail::array_deleter d1; + T3* p2 = 0; + boost::detail::allocate_array_helper a1(allocator, &p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; + typedef boost::detail::array_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); d2->noinit(p2); diff --git a/include/boost/smart_ptr/detail/array_deleter.hpp b/include/boost/smart_ptr/detail/array_deleter.hpp index 6db78c8..9d7f970 100644 --- a/include/boost/smart_ptr/detail/array_deleter.hpp +++ b/include/boost/smart_ptr/detail/array_deleter.hpp @@ -9,6 +9,7 @@ #ifndef BOOST_SMART_PTR_DETAIL_ARRAY_DELETER_HPP #define BOOST_SMART_PTR_DETAIL_ARRAY_DELETER_HPP +#include #include namespace boost { @@ -35,9 +36,9 @@ namespace boost { object = memory; } - template - void init(T* memory, const T* list) { - array_init(memory, size, list); + template + void init(T* memory, const T* value) { + array_init(memory, size, value); object = memory; } @@ -77,8 +78,8 @@ namespace boost { } template - void init(T* memory, const T* list) { - array_init(memory, N, list); + void init(T* memory, const T* value) { + array_init(memory, N, value); object = memory; } diff --git a/include/boost/smart_ptr/detail/array_traits.hpp b/include/boost/smart_ptr/detail/array_traits.hpp index 712efbb..e10ef97 100644 --- a/include/boost/smart_ptr/detail/array_traits.hpp +++ b/include/boost/smart_ptr/detail/array_traits.hpp @@ -9,13 +9,13 @@ #ifndef BOOST_SMART_PTR_DETAIL_ARRAY_TRAITS_HPP #define BOOST_SMART_PTR_DETAIL_ARRAY_TRAITS_HPP -#include +#include namespace boost { namespace detail { template struct array_base { - typedef typename boost::remove_cv::type type; + typedef T type; }; template diff --git a/include/boost/smart_ptr/detail/array_utility.hpp b/include/boost/smart_ptr/detail/array_utility.hpp index cea2865..d8444b8 100644 --- a/include/boost/smart_ptr/detail/array_utility.hpp +++ b/include/boost/smart_ptr/detail/array_utility.hpp @@ -16,11 +16,13 @@ namespace boost { namespace detail { template - inline void array_destroy(T*, std::size_t, boost::true_type) { + inline void array_destroy(T*, std::size_t, + boost::true_type) { } template - inline void array_destroy(T* memory, std::size_t size, boost::false_type) { + inline void array_destroy(T* memory, std::size_t size, + boost::false_type) { for (std::size_t i = size; i > 0; ) { memory[--i].~T(); } @@ -33,7 +35,8 @@ namespace boost { } template - inline void array_value(T* memory, std::size_t size, boost::true_type) { + inline void array_value(T* memory, std::size_t size, + boost::true_type) { for (std::size_t i = 0; i < size; i++) { void* p1 = memory + i; ::new(p1) T(); @@ -41,7 +44,8 @@ namespace boost { } template - inline void array_value(T* memory, std::size_t size, boost::false_type) { + inline void array_value(T* memory, std::size_t size, + boost::false_type) { #if !defined(BOOST_NO_EXCEPTIONS) std::size_t i = 0; try { @@ -68,7 +72,8 @@ namespace boost { } template - inline void array_init(T* memory, std::size_t size, const T* list) { + inline void array_init(T* memory, std::size_t size, + const T* list) { #if !defined(BOOST_NO_EXCEPTIONS) std::size_t i = 0; try { @@ -89,11 +94,13 @@ namespace boost { } template - inline void array_default(T*, std::size_t, boost::true_type) { + inline void array_default(T*, std::size_t, + boost::true_type) { } template - inline void array_default(T* memory, std::size_t size, boost::false_type) { + inline void array_default(T* memory, std::size_t size, + boost::false_type) { #if !defined(BOOST_NO_EXCEPTIONS) std::size_t i = 0; try { diff --git a/include/boost/smart_ptr/make_shared_array.hpp b/include/boost/smart_ptr/make_shared_array.hpp index 7dc952e..6a0bcfd 100644 --- a/include/boost/smart_ptr/make_shared_array.hpp +++ b/include/boost/smart_ptr/make_shared_array.hpp @@ -9,11 +9,11 @@ #ifndef BOOST_SMART_PTR_MAKE_SHARED_ARRAY_HPP #define BOOST_SMART_PTR_MAKE_SHARED_ARRAY_HPP -#include #include #include #include #include +#include namespace boost { template @@ -21,13 +21,14 @@ namespace boost { make_shared(std::size_t size) { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; + typedef typename boost::remove_cv::type T3; T1* p1 = 0; - T2* p2 = 0; + T3* p2 = 0; std::size_t n1 = size * boost::detail::array_total::size; - boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1(n1); + boost::detail::make_array_helper a1(n1, &p2); + boost::detail::array_deleter d1(n1); boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; + typedef boost::detail::array_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); d2->init(p2); @@ -39,15 +40,16 @@ namespace boost { make_shared() { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; + typedef typename boost::remove_cv::type T3; enum { N = boost::detail::array_total::size }; T1* p1 = 0; - T2* p2 = 0; - boost::detail::make_array_helper a1(&p2); - boost::detail::array_deleter d1; + T3* p2 = 0; + boost::detail::make_array_helper a1(&p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; + typedef boost::detail::array_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); d2->init(p2); @@ -57,22 +59,22 @@ namespace boost { template inline typename boost::detail::sp_if_array::type make_shared(std::size_t size, - const typename boost::detail::array_inner::type& list) { + const typename boost::detail::array_inner::type& value) { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; - typedef const T2 T3; + typedef typename boost::remove_cv::type T3; + typedef const T2 T4; enum { M = boost::detail::array_total::size }; T1* p1 = 0; - T2* p2 = 0; - T3* p3 = 0; + T3* p2 = 0; + T4* p3 = reinterpret_cast(&value); std::size_t n1 = M * size; - boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1(n1); + boost::detail::make_array_helper a1(n1, &p2); + boost::detail::array_deleter d1(n1); boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; - p3 = reinterpret_cast(&list); + typedef boost::detail::array_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); d2->template init(p2, p3); @@ -81,22 +83,22 @@ namespace boost { template inline typename boost::detail::sp_if_size_array::type - make_shared(const typename boost::detail::array_inner::type& list) { + make_shared(const typename boost::detail::array_inner::type& value) { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; - typedef const T2 T3; + typedef typename boost::remove_cv::type T3; + typedef const T2 T4; enum { M = boost::detail::array_total::size, N = boost::detail::array_total::size }; T1* p1 = 0; - T2* p2 = 0; - T3* p3 = 0; - boost::detail::make_array_helper a1(&p2); - boost::detail::array_deleter d1; + T3* p2 = 0; + T4* p3 = reinterpret_cast(&value); + boost::detail::make_array_helper a1(&p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; - p3 = reinterpret_cast(&list); + typedef boost::detail::array_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); d2->template init(p2, p3); @@ -108,13 +110,14 @@ namespace boost { make_shared_noinit(std::size_t size) { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; + typedef typename boost::remove_cv::type T3; T1* p1 = 0; - T2* p2 = 0; + T3* p2 = 0; std::size_t n1 = size * boost::detail::array_total::size; - boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1(n1); + boost::detail::make_array_helper a1(n1, &p2); + boost::detail::array_deleter d1(n1); boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; + typedef boost::detail::array_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); d2->noinit(p2); @@ -126,15 +129,16 @@ namespace boost { make_shared_noinit() { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; + typedef typename boost::remove_cv::type T3; enum { N = boost::detail::array_total::size }; T1* p1 = 0; - T2* p2 = 0; - boost::detail::make_array_helper a1(&p2); - boost::detail::array_deleter d1; + T3* p2 = 0; + boost::detail::make_array_helper a1(&p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; + typedef boost::detail::array_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); d2->noinit(p2); diff --git a/test/allocate_shared_array_test.cpp b/test/allocate_shared_array_test.cpp index 737e736..43715a7 100644 --- a/test/allocate_shared_array_test.cpp +++ b/test/allocate_shared_array_test.cpp @@ -5,7 +5,7 @@ * Distributed under the Boost Software License, * Version 1.0. (See accompanying file LICENSE_1_0.txt * or copy at http://boost.org/LICENSE_1_0.txt) -*/ + */ #include #include #include diff --git a/test/allocate_shared_array_throws_test.cpp b/test/allocate_shared_array_throws_test.cpp index 79beaeb..71a3ce9 100644 --- a/test/allocate_shared_array_throws_test.cpp +++ b/test/allocate_shared_array_throws_test.cpp @@ -84,8 +84,7 @@ int main() { try { boost::allocate_shared_noinit(std::allocator()); BOOST_ERROR("allocate_shared_noinit did not throw"); - } - catch (...) { + } catch (...) { BOOST_TEST(type::instances == 0); } @@ -93,8 +92,7 @@ int main() { try { boost::allocate_shared_noinit(std::allocator()); BOOST_ERROR("allocate_shared_noinit did not throw"); - } - catch (...) { + } catch (...) { BOOST_TEST(type::instances == 0); } diff --git a/test/make_shared_array_throws_test.cpp b/test/make_shared_array_throws_test.cpp index 98d6ea7..151ab31 100644 --- a/test/make_shared_array_throws_test.cpp +++ b/test/make_shared_array_throws_test.cpp @@ -84,8 +84,7 @@ int main() { try { boost::make_shared_noinit(); BOOST_ERROR("make_shared_noinit did not throw"); - } - catch (...) { + } catch (...) { BOOST_TEST(type::instances == 0); } @@ -93,8 +92,7 @@ int main() { try { boost::make_shared_noinit(); BOOST_ERROR("make_shared_noinit did not throw"); - } - catch (...) { + } catch (...) { BOOST_TEST(type::instances == 0); } From 7806737b523a650fcf164916f073424b772039dd Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Tue, 28 Jan 2014 03:58:51 -0800 Subject: [PATCH 14/39] Add make_unique for arrays and objects --- .../boost/smart_ptr/detail/up_if_array.hpp | 26 ++++ .../smart_ptr/detail/up_if_not_array.hpp | 31 ++++ include/boost/smart_ptr/make_unique.hpp | 15 ++ include/boost/smart_ptr/make_unique_array.hpp | 31 ++++ .../boost/smart_ptr/make_unique_object.hpp | 37 +++++ test/Jamfile.v2 | 8 + test/make_unique_args_test.cpp | 139 ++++++++++++++++++ test/make_unique_array_noinit_test.cpp | 93 ++++++++++++ test/make_unique_array_test.cpp | 106 +++++++++++++ test/make_unique_array_throws_test.cpp | 71 +++++++++ test/make_unique_noinit_test.cpp | 64 ++++++++ test/make_unique_test.cpp | 65 ++++++++ test/make_unique_throws_test.cpp | 46 ++++++ 13 files changed, 732 insertions(+) create mode 100644 include/boost/smart_ptr/detail/up_if_array.hpp create mode 100644 include/boost/smart_ptr/detail/up_if_not_array.hpp create mode 100644 include/boost/smart_ptr/make_unique.hpp create mode 100644 include/boost/smart_ptr/make_unique_array.hpp create mode 100644 include/boost/smart_ptr/make_unique_object.hpp create mode 100644 test/make_unique_args_test.cpp create mode 100644 test/make_unique_array_noinit_test.cpp create mode 100644 test/make_unique_array_test.cpp create mode 100644 test/make_unique_array_throws_test.cpp create mode 100644 test/make_unique_noinit_test.cpp create mode 100644 test/make_unique_test.cpp create mode 100644 test/make_unique_throws_test.cpp diff --git a/include/boost/smart_ptr/detail/up_if_array.hpp b/include/boost/smart_ptr/detail/up_if_array.hpp new file mode 100644 index 0000000..d0b197d --- /dev/null +++ b/include/boost/smart_ptr/detail/up_if_array.hpp @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2014 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#ifndef BOOST_SMART_PTR_DETAIL_UP_IF_ARRAY_HPP +#define BOOST_SMART_PTR_DETAIL_UP_IF_ARRAY_HPP + +#include + +namespace boost { + namespace detail { + template + struct up_if_array; + + template + struct up_if_array { + typedef std::unique_ptr type; + }; + } +} + +#endif diff --git a/include/boost/smart_ptr/detail/up_if_not_array.hpp b/include/boost/smart_ptr/detail/up_if_not_array.hpp new file mode 100644 index 0000000..7679e61 --- /dev/null +++ b/include/boost/smart_ptr/detail/up_if_not_array.hpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2014 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#ifndef BOOST_SMART_PTR_DETAIL_UP_IF_NOT_ARRAY_HPP +#define BOOST_SMART_PTR_DETAIL_UP_IF_NOT_ARRAY_HPP + +#include + +namespace boost { + namespace detail { + template + struct up_if_not_array { + typedef std::unique_ptr type; + }; + + template + struct up_if_not_array { + }; + + template + struct up_if_not_array { + }; + } +} + +#endif diff --git a/include/boost/smart_ptr/make_unique.hpp b/include/boost/smart_ptr/make_unique.hpp new file mode 100644 index 0000000..90402e2 --- /dev/null +++ b/include/boost/smart_ptr/make_unique.hpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2014 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#ifndef BOOST_SMART_PTR_MAKE_UNIQUE_HPP +#define BOOST_SMART_PTR_MAKE_UNIQUE_HPP + +#include +#include + +#endif diff --git a/include/boost/smart_ptr/make_unique_array.hpp b/include/boost/smart_ptr/make_unique_array.hpp new file mode 100644 index 0000000..987c565 --- /dev/null +++ b/include/boost/smart_ptr/make_unique_array.hpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2014 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#ifndef BOOST_SMART_PTR_MAKE_UNIQUE_ARRAY_HPP +#define BOOST_SMART_PTR_MAKE_UNIQUE_ARRAY_HPP + +#include +#include + +namespace boost { + template + inline typename boost::detail::up_if_array::type + make_unique(std::size_t size) { + typedef typename boost::detail::array_inner::type U; + return std::unique_ptr(new U[size]()); + } + + template + inline typename boost::detail::up_if_array::type + make_unique_noinit(std::size_t size) { + typedef typename boost::detail::array_inner::type U; + return std::unique_ptr(new U[size]); + } +} + +#endif diff --git a/include/boost/smart_ptr/make_unique_object.hpp b/include/boost/smart_ptr/make_unique_object.hpp new file mode 100644 index 0000000..3ebdabd --- /dev/null +++ b/include/boost/smart_ptr/make_unique_object.hpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#ifndef BOOST_SMART_PTR_MAKE_UNIQUE_OBJECT_HPP +#define BOOST_SMART_PTR_MAKE_UNIQUE_OBJECT_HPP + +#include +#include + +namespace boost { + template + inline typename boost::detail::up_if_not_array::type + make_unique() { + return std::unique_ptr(new T()); + } + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template + inline typename boost::detail::up_if_not_array::type + make_unique(Args&&... args) { + return std::unique_ptr(new T(std::forward(args)...)); + } +#endif + + template + inline typename boost::detail::up_if_not_array::type + make_unique_noinit() { + return std::unique_ptr(new T); + } +} + +#endif diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 60cf992..6cb4243 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -148,5 +148,13 @@ import testing ; [ run allocate_shared_array_esft_test.cpp ] [ run allocate_shared_array_noinit_test.cpp ] [ run allocate_shared_array_value_test.cpp ] + + [ run make_unique_test.cpp ] + [ run make_unique_args_test.cpp ] + [ run make_unique_noinit_test.cpp ] + [ run make_unique_throws_test.cpp ] + [ run make_unique_array_test.cpp ] + [ run make_unique_array_noinit_test.cpp ] + [ run make_unique_array_throws_test.cpp ] ; } diff --git a/test/make_unique_args_test.cpp b/test/make_unique_args_test.cpp new file mode 100644 index 0000000..d502b30 --- /dev/null +++ b/test/make_unique_args_test.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2014 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include + +class type { +public: + static unsigned int instances; + + explicit type(int v1 = 0, + int v2 = 0, + int v3 = 0, + int v4 = 0, + int v5 = 0, + int v6 = 0, + int v7 = 0, + int v8 = 0, + int v9 = 0) + : sum(v1 + v2 + v3 + v4 + v5 + v6 + v7 + v8 + v9) { + instances++; + } + + ~type() { + instances--; + } + + const int sum; + +private: + type(const type&); + type& operator=(const type&); +}; + +unsigned int type::instances = 0; + +int main() { +#if !defined(BOOST_NO_CXX11_SMART_PTR) + BOOST_TEST(type::instances == 0); + { + std::unique_ptr a1 = boost::make_unique(); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(type::instances == 1); + BOOST_TEST(a1->sum == 0); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + +#if !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) + { + std::unique_ptr a1 = boost::make_unique(1); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(type::instances == 1); + BOOST_TEST(a1->sum == 1); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + { + std::unique_ptr a1 = boost::make_unique(1, 2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(type::instances == 1); + BOOST_TEST(a1->sum == 1 + 2); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + { + std::unique_ptr a1 = boost::make_unique(1, 2, 3); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(type::instances == 1); + BOOST_TEST(a1->sum == 1 + 2 + 3); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + { + std::unique_ptr a1 = boost::make_unique(1, 2, 3, 4); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(type::instances == 1); + BOOST_TEST(a1->sum == 1 + 2 + 3 + 4); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + { + std::unique_ptr a1 = boost::make_unique(1, 2, 3, 4, 5); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(type::instances == 1); + BOOST_TEST(a1->sum == 1 + 2 + 3 + 4 + 5); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + { + std::unique_ptr a1 = boost::make_unique(1, 2, 3, 4, 5, 6); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(type::instances == 1); + BOOST_TEST(a1->sum == 1 + 2 + 3 + 4 + 5 + 6); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + { + std::unique_ptr a1 = boost::make_unique(1, 2, 3, 4, 5, 6, 7); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(type::instances == 1); + BOOST_TEST(a1->sum == 1 + 2 + 3 + 4 + 5 + 6 + 7); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + { + std::unique_ptr a1 = boost::make_unique(1, 2, 3, 4, 5, 6, 7, 8); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(type::instances == 1); + BOOST_TEST(a1->sum == 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + { + std::unique_ptr a1 = boost::make_unique(1, 2, 3, 4, 5, 6, 7, 8, 9); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(type::instances == 1); + BOOST_TEST(a1->sum == 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9); + a1.reset(); + BOOST_TEST(type::instances == 0); + } +#endif +#endif + + return boost::report_errors(); +} diff --git a/test/make_unique_array_noinit_test.cpp b/test/make_unique_array_noinit_test.cpp new file mode 100644 index 0000000..68b6056 --- /dev/null +++ b/test/make_unique_array_noinit_test.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2012-2014 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include +#include + +class type { +public: + static unsigned int instances; + + explicit type() { + instances++; + } + + ~type() { + instances--; + } + +private: + type(const type&); + type& operator=(const type&); +}; + +unsigned int type::instances = 0; + +int main() { +#if !defined(BOOST_NO_CXX11_SMART_PTR) + { + std::unique_ptr a1 = boost::make_unique_noinit(3); + BOOST_TEST(a1.get() != 0); + } + + { + std::unique_ptr a1 = boost::make_unique_noinit(2); + BOOST_TEST(a1.get() != 0); + } + + { + std::unique_ptr a1 = boost::make_unique_noinit(3); + BOOST_TEST(a1.get() != 0); + } + + { + std::unique_ptr a1 = boost::make_unique_noinit(2); + BOOST_TEST(a1.get() != 0); + } + + BOOST_TEST(type::instances == 0); + { + std::unique_ptr a1 = boost::make_unique_noinit(3); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(type::instances == 3); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + BOOST_TEST(type::instances == 0); + { + std::unique_ptr a1 = boost::make_unique_noinit(2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(type::instances == 4); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + BOOST_TEST(type::instances == 0); + { + std::unique_ptr a1 = boost::make_unique_noinit(3); + const type* a2 = a1.get(); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(type::instances == 3); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + BOOST_TEST(type::instances == 0); + { + std::unique_ptr a1 = boost::make_unique_noinit(2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(type::instances == 4); + a1.reset(); + BOOST_TEST(type::instances == 0); + } +#endif + + return boost::report_errors(); +} diff --git a/test/make_unique_array_test.cpp b/test/make_unique_array_test.cpp new file mode 100644 index 0000000..21808af --- /dev/null +++ b/test/make_unique_array_test.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2014 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include +#include + +class type { +public: + static unsigned int instances; + + explicit type() { + instances++; + } + + ~type() { + instances--; + } + +private: + type(const type&); + type& operator=(const type&); +}; + +unsigned int type::instances = 0; + +int main() { +#if !defined(BOOST_NO_CXX11_SMART_PTR) + { + std::unique_ptr a1 = boost::make_unique(3); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 0); + BOOST_TEST(a1[2] == 0); + } + + { + std::unique_ptr a1 = boost::make_unique(2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1[0][0] == 0); + BOOST_TEST(a1[0][1] == 0); + BOOST_TEST(a1[1][0] == 0); + BOOST_TEST(a1[1][1] == 0); + } + + { + std::unique_ptr a1 = boost::make_unique(3); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 0); + BOOST_TEST(a1[2] == 0); + } + + { + std::unique_ptr a1 = boost::make_unique(2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1[0][0] == 0); + BOOST_TEST(a1[0][1] == 0); + BOOST_TEST(a1[1][0] == 0); + BOOST_TEST(a1[1][1] == 0); + } + + BOOST_TEST(type::instances == 0); + { + std::unique_ptr a1 = boost::make_unique(3); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(type::instances == 3); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + BOOST_TEST(type::instances == 0); + { + std::unique_ptr a1 = boost::make_unique(2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(type::instances == 4); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + BOOST_TEST(type::instances == 0); + { + std::unique_ptr a1 = boost::make_unique(3); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(type::instances == 3); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + BOOST_TEST(type::instances == 0); + { + std::unique_ptr a1 = boost::make_unique(2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(type::instances == 4); + a1.reset(); + BOOST_TEST(type::instances == 0); + } +#endif + + return boost::report_errors(); +} diff --git a/test/make_unique_array_throws_test.cpp b/test/make_unique_array_throws_test.cpp new file mode 100644 index 0000000..dc48fa1 --- /dev/null +++ b/test/make_unique_array_throws_test.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2014 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include +#include + +class type { +public: + static unsigned int instances; + + explicit type() { + if (instances == 5) { + throw true; + } + instances++; + } + + ~type() { + instances--; + } + +private: + type(const type&); + type& operator=(const type&); +}; + +unsigned int type::instances = 0; + +int main() { +#if !defined(BOOST_NO_CXX11_SMART_PTR) + BOOST_TEST(type::instances == 0); + try { + boost::make_unique(6); + BOOST_ERROR("make_unique did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } + + BOOST_TEST(type::instances == 0); + try { + boost::make_unique(3); + BOOST_ERROR("make_unique did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } + + BOOST_TEST(type::instances == 0); + try { + boost::make_unique_noinit(6); + BOOST_ERROR("make_unique_noinit did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } + + BOOST_TEST(type::instances == 0); + try { + boost::make_unique_noinit(3); + BOOST_ERROR("make_unique_noinit did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } +#endif + + return boost::report_errors(); +} diff --git a/test/make_unique_noinit_test.cpp b/test/make_unique_noinit_test.cpp new file mode 100644 index 0000000..406c958 --- /dev/null +++ b/test/make_unique_noinit_test.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2012-2014 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include + +class type { +public: + static unsigned int instances; + + explicit type() { + instances++; + } + + ~type() { + instances--; + } + +private: + type(const type&); + type& operator=(const type&); +}; + +unsigned int type::instances = 0; + +int main() { +#if !defined(BOOST_NO_CXX11_SMART_PTR) + { + std::unique_ptr a1 = boost::make_unique_noinit(); + BOOST_TEST(a1.get() != 0); + } + + { + std::unique_ptr a1 = boost::make_unique_noinit(); + BOOST_TEST(a1.get() != 0); + } + + BOOST_TEST(type::instances == 0); + { + std::unique_ptr a1 = boost::make_unique_noinit(); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(type::instances == 1); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + BOOST_TEST(type::instances == 0); + { + std::unique_ptr a1 = boost::make_unique_noinit(); + const type* a2 = a1.get(); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(type::instances == 1); + a1.reset(); + BOOST_TEST(type::instances == 0); + } +#endif + + return boost::report_errors(); +} diff --git a/test/make_unique_test.cpp b/test/make_unique_test.cpp new file mode 100644 index 0000000..6106ac3 --- /dev/null +++ b/test/make_unique_test.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2014 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include + +class type { +public: + static unsigned int instances; + + explicit type() { + instances++; + } + + ~type() { + instances--; + } + +private: + type(const type&); + type& operator=(const type&); +}; + +unsigned int type::instances = 0; + +int main() { +#if !defined(BOOST_NO_CXX11_SMART_PTR) + { + std::unique_ptr a1 = boost::make_unique(); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(*a1 == 0); + } + + { + std::unique_ptr a1 = boost::make_unique(); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(*a1 == 0); + } + + BOOST_TEST(type::instances == 0); + { + std::unique_ptr a1 = boost::make_unique(); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(type::instances == 1); + a1.reset(); + BOOST_TEST(type::instances == 0); + } + + BOOST_TEST(type::instances == 0); + { + std::unique_ptr a1 = boost::make_unique(); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(type::instances == 1); + a1.reset(); + BOOST_TEST(type::instances == 0); + } +#endif + + return boost::report_errors(); +} diff --git a/test/make_unique_throws_test.cpp b/test/make_unique_throws_test.cpp new file mode 100644 index 0000000..bf9e5bf --- /dev/null +++ b/test/make_unique_throws_test.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include + +class type { +public: + static unsigned int instances; + + explicit type() { + if (instances == 0) { + throw true; + } + instances++; + } + + ~type() { + instances--; + } + +private: + type(const type&); + type& operator=(const type&); +}; + +unsigned int type::instances = 0; + +int main() { +#if !defined(BOOST_NO_CXX11_SMART_PTR) + BOOST_TEST(type::instances == 0); + try { + boost::make_unique(); + BOOST_ERROR("make_unique did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } +#endif + + return boost::report_errors(); +} From ad658fa5ec67201a6598cef4cd9617c065dd78a1 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Wed, 29 Jan 2014 05:42:42 -0800 Subject: [PATCH 15/39] Update make shared for arrays documentation --- make_shared_array.html | 108 +++++++++++++++++++++++------------------ smart_ptr.htm | 2 +- 2 files changed, 61 insertions(+), 49 deletions(-) diff --git a/make_shared_array.html b/make_shared_array.html index 6959ca1..e7d80d4 100644 --- a/make_shared_array.html +++ b/make_shared_array.html @@ -1,32 +1,33 @@ - + - make_shared and allocate_shared + make_shared and allocate_shared for arrays - +

boost.png (6897 bytes)make_shared and allocate_shared for arrays

-

Introduction
- Synopsis
- Free Functions
- Example
- History

+

Introduction
+ Synopsis
+ Free Functions
+ Examples
+ History
+ References

Introduction

Originally the Boost function templates make_shared and - allocate_shared were for efficient allocation of single - objects only. There was a need to have efficient, single, allocation of - arrays. One criticism of shared_array was - always the lack of a make_shared utility - which ensures only a single allocation for an array.

+ allocate_shared were for efficient allocation of shared + objects only. There was a need to have efficient allocation of + shared arrays. One criticism of class template shared_array + was always the lack of a make_shared + utility which ensures only a single allocation.

The header files <boost/smart_ptr/make_shared_array.hpp> and - <boost/smart_ptr/allocate_shared_array.hpp> provide new function - templates, make_shared and allocate_shared, - to address this need. make_shared uses the global - operator new to allocate memory, whereas - allocate_shared uses an user-supplied allocator, - allowing finer control.

+ <boost/smart_ptr/allocate_shared_array.hpp> provide function + templates, overloads of make_shared and + allocate_shared for array types, to address this need. + make_shared uses the global operator new to + allocate memory, whereas allocate_shared uses an + user-supplied allocator, allowing finer control.

Synopsis

namespace boost {
     template<typename U> // U is T[]
@@ -80,18 +81,17 @@ shared_ptr<U> allocate_shared(const A& allocator);

Requires: The expression new(pointer) T(), where pointer is a - void* pointing to storage suitable to hold an object - of type T, shall be well-formed. A - shall be an Allocator, as described in section 20.1.5 - (Allocator requirements) of the C++ Standard. - The copy constructor and destructor of A shall not - throw.

+ void* pointing to storage suitable to hold an object of + type T, shall be well-formed. A shall be an + Allocator, as described in section 20.1.5 (Allocator + requirements) of the C++ Standard. The copy constructor and + destructor of A shall not throw.

Effects: Allocates memory suitable for an array of type - T and size size and constructs an array - of objects in it via the placement new expression - new(pointer) T(). allocate_shared uses - a copy of allocator to allocate memory. If an - exception is thrown, has no effect.

+ T and size size and constructs an array of + objects in it via the placement new expression new(pointer) + T(). allocate_shared uses a copy of + allocator to allocate memory. If an exception is thrown, + has no effect.

Returns: A shared_ptr instance that stores and owns the address of the newly constructed array of type T and size size.

@@ -102,8 +102,7 @@ shared_ptr<U> allocate_shared(const A& allocator);

Notes: This implementation allocates the memory required for the returned shared_ptr and an array of type T of size size in a single allocation. This - provides efficiency to equivalent to an intrusive smart array - pointer.

+ provides efficiency to equivalent to an intrusive smart pointer.

template<typename U> // U is T[]
 shared_ptr<U> make_shared(size_t size, const T& value);
@@ -117,8 +116,8 @@ shared_ptr<U> make_shared(const T& value);
 template<typename U, typename A> // U is T[N]
 shared_ptr<U> allocate_shared(const A& allocator, const T& value);
-

Description: These overloads initialize array elements with - the given value.

+

Notes: These overloads initialize array objects with the given + value.

template<typename U> // U is T[]
 shared_ptr<U> make_shared_noinit(size_t size);
@@ -132,28 +131,41 @@ shared_ptr<U> make_shared_noinit();
 template<typename U, typename A> // U is T[N]
 shared_ptr<U> allocate_shared_noinit(const A& allocator);
-

Description: These overloads do not perform any value - initialization of elements.

+

Notes: These overloads do not perform value initialization of + array objects.

Examples

-

Some examples of each overload of make_shared for arrays:

+

The following examples value-initialize objects.

-
boost::shared_ptr<int[]> a1 = boost::make_shared<int[]>(size);
-boost::shared_ptr<int[8]> a2 = boost::make_shared<int[8]>();
-boost::shared_ptr<int[][2]> a3 = boost::make_shared<int[][2]>(size);
-boost::shared_ptr<int[4][2]> a4 = boost::make_shared<int[4][2]>();
-boost::shared_ptr<int[]> a5 = boost::make_shared<int[]>(size, 1);
-boost::shared_ptr<int[8]> a6 = boost::make_shared<int[8]>(1);
-boost::shared_ptr<int[][2]> a7 = boost::make_shared<int[][2]>(size, {1, 2});
-boost::shared_ptr<int[4][2]> a8 = boost::make_shared<int[4][2]>({1, 2});
-boost::shared_ptr<int[]> a9 = boost::make_shared_noinit<int[]>(size);
-boost::shared_ptr<int[8]> a10 = boost::make_shared_noinit<int[8]>();
-boost::shared_ptr<int[][2]> a11 = boost::make_shared_noinit<int[][2]>(size);
+      
boost::shared_ptr<int[]>     a1  = boost::make_shared<int[]>(size);
+boost::shared_ptr<int[8]>    a2  = boost::make_shared<int[8]>();
+boost::shared_ptr<int[][2]>  a3  = boost::make_shared<int[][2]>(size);
+boost::shared_ptr<int[4][2]> a4  = boost::make_shared<int[4][2]>();
+
+

The following examples initialize objects with a given value.

+
+
boost::shared_ptr<int[]>     a5  = boost::make_shared<int[]>(size, 1);
+boost::shared_ptr<int[8]>    a6  = boost::make_shared<int[8]>(1);
+boost::shared_ptr<int[][2]>  a7  = boost::make_shared<int[][2]>(size, {1, 2});
+boost::shared_ptr<int[4][2]> a8  = boost::make_shared<int[4][2]>({1, 2});
+
+

The following examples default-initialize objects.

+
+
boost::shared_ptr<int[]>     a9  = boost::make_shared_noinit<int[]>(size);
+boost::shared_ptr<int[8]>    a10 = boost::make_shared_noinit<int[8]>();
+boost::shared_ptr<int[][2]>  a11 = boost::make_shared_noinit<int[][2]>(size);
 boost::shared_ptr<int[4][2]> a12 = boost::make_shared_noinit<int[4][2]>();

History

+

January 2014. Glen Fernandes reduced the overloads of make_shared and + allocate_shared according to N3870.

November 2012. Glen Fernandes contributed implementations of make_shared and allocate_shared for arrays.

+

References

+

N3870, + + Extending make_shared to Support Arrays, Revision 1, Peter Dimov + & Glen Fernandes, January, 2014.


$Date: 2014-01-20 11:10:00 -0800 (Mon, 20 Jan 2014) $

Copyright 2012-2014 Glen Fernandes. Distributed under the diff --git a/smart_ptr.htm b/smart_ptr.htm index 2aba306..5fcfbb3 100644 --- a/smart_ptr.htm +++ b/smart_ptr.htm @@ -66,7 +66,7 @@

- + From 7fef3bb40b10badd8f6783b8e38b288e086c074c Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Wed, 29 Jan 2014 07:25:30 -0800 Subject: [PATCH 16/39] Add top-level make_unique.hpp and documentation --- include/boost/make_unique.hpp | 14 ++++ make_unique.html | 124 ++++++++++++++++++++++++++++++++++ smart_ptr.htm | 8 +++ 3 files changed, 146 insertions(+) create mode 100644 include/boost/make_unique.hpp create mode 100644 make_unique.html diff --git a/include/boost/make_unique.hpp b/include/boost/make_unique.hpp new file mode 100644 index 0000000..c163673 --- /dev/null +++ b/include/boost/make_unique.hpp @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2014 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#ifndef BOOST_MAKE_UNIQUE_HPP_INCLUDED +#define BOOST_MAKE_UNIQUE_HPP_INCLUDED + +#include + +#endif diff --git a/make_unique.html b/make_unique.html new file mode 100644 index 0000000..b6d7a7d --- /dev/null +++ b/make_unique.html @@ -0,0 +1,124 @@ + + + + make_unique + + + +

boost.png (6897 bytes)make_unique

+

Introduction
+ Synopsis
+ Free Functions
+ Examples
+ History

+

Introduction

+

The header file <boost/make_unique.hpp> provides a family of + overloaded function template make_unique for convenient + creation of unique_ptr objects.

+

Synopsis

+
namespace boost {
+    template<typename U> // U is not array
+    unique_ptr<U> make_unique();
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+    template<typename U, typename... Args> // U is not array
+    unique_ptr<U> make_unique(Args&&... args);
+#endif
+
+    template<typename U> // U is not array
+    unique_ptr<U> make_unique_noinit();
+
+    template<typename U> // U is T[]
+    unique_ptr<U> make_unique(size_t size);
+
+    template<typename U> // U is T[]
+    unique_ptr<U> make_unique_noinit(size_t size);
+}
+

Free Functions

+
template<typename U> // U is not array
+unique_ptr<U> make_unique();
+
+

Requires: The expression new U() shall be + well-formed.

+

Effects: Constructs an object of type U via the + expression new U().

+

Returns: A unique_ptr instance that stores and + owns the address of the newly constructed object.

+

Postconditions: get() != 0.

+

Throws: bad_alloc, or an exception thrown from + the constructor of U.

+
+
template<typename U, typename... Args> // U is not array
+unique_ptr<U> make_unique(Args&&... args);
+
+

Requires: The expression + new U(forward<Args>(args)...) shall be + well-formed.

+

Effects: Constructs an object of type U via the + expression new U(forward<Args>(args)...).

+
+
template<typename U> // U is not array
+unique_ptr<U> make_unique_noinit();
+
+

Requires: The expression new U shall be + well-formed.

+

Effects: Constructs an object of type U via the + expression new U.

+
+
template<typename U> // U is T[]
+unique_ptr<U> make_unique(size_t size);
+
+

Requires: The expression new U() shall be + well-formed.

+

Effects: Constructs an array of objects of type + U and size size via the expression + new U[size]().

+
+
template<typename U> // U is T[]
+unique_ptr<U> make_unique_noinit(size_t size);
+
+

Requires: The expression new U shall be + well-formed.

+

Effects: Constructs an array of objects of type + U and size size via the expression + new U[size].

+
+

Examples

+

For objects with value-initialization.

+
+
std::unique_ptr<float> p1 = boost::make_unique<float>();
+std::unique_ptr<point> p2 = boost::make_unique<point>();
+
+

For objects with construction arguments.

+
+
std::unique_ptr<float> p3 = boost::make_unique<float>(1.5);
+std::unique_ptr<point> p4 = boost::make_unique<point>(x, y);
+
+

For objects with default-initialization.

+
+
std::unique_ptr<float> p4 = boost::make_unique_noinit<float>();
+std::unique_ptr<point> p5 = boost::make_unique_noinit<point>();
+
+

For arrays with value-initialization.

+
+
std::unique_ptr<double[]> a1 = boost::make_unique<double[]>();
+std::unique_ptr<int[][4]> a2 = boost::make_unique<int[][4]>();
+
+

For arrays with default-initialization.

+
+
std::unique_ptr<double[]> a3 = boost::make_unique_noinit<double[]>();
+std::unique_ptr<int[][4]> a4 = boost::make_unique_noinit<int[][4]>();
+
+

History

+

January 2014. Glen Fernandes contributed implementations of + make_unique for objects and arrays.

+
+

$Date: 2014-01-20 11:10:00 -0800 (Mon, 20 Jan 2014) $

+

Copyright 2012-2014 Glen Fernandes. 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.

+ + diff --git a/smart_ptr.htm b/smart_ptr.htm index 5fcfbb3..c16dceb 100644 --- a/smart_ptr.htm +++ b/smart_ptr.htm @@ -75,6 +75,11 @@
+ + + + +
make_shared and allocate_sharedmake_shared and allocate_shared for objects <boost/make_shared.hpp> Efficient creation of shared_ptr objects.
<boost/make_shared.hpp> Efficient creation of shared_ptr arrays.
make_unique<boost/make_unique.hpp>Creation of unique_ptr objects and arrays.

A test program, smart_ptr_test.cpp, is @@ -131,6 +136,9 @@

Functions which destroy objects of the pointed to type are prohibited from throwing exceptions by the common requirements.

History and Acknowledgements

+

January 2014. Glen Fernandes confined the overloads of make_shared + and allocate_shared for arrays to the specification in N3870 and + implemented make_unique for arrays and objects.

November 2012. Glen Fernandes provided implementations of make_shared and allocate_shared for arrays. They achieve a single allocation for an array that can be initialized with constructor arguments or initializer lists From f91e7e9ce77c852a5cb8998f5b7749d5ba42dfa2 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Wed, 29 Jan 2014 09:15:47 -0800 Subject: [PATCH 17/39] Minor documentation corrections --- make_unique.html | 14 +++++++------- smart_ptr.htm | 7 ++++--- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/make_unique.html b/make_unique.html index b6d7a7d..ab4db62 100644 --- a/make_unique.html +++ b/make_unique.html @@ -13,9 +13,9 @@ Examples
History

Introduction

-

The header file <boost/make_unique.hpp> provides a family of - overloaded function template make_unique for convenient - creation of unique_ptr objects.

+

The header file <boost/make_unique.hpp> provides overloaded + function template make_unique for convenient creation of + unique_ptr objects.

Synopsis

namespace boost {
     template<typename U> // U is not array
@@ -69,20 +69,20 @@ unique_ptr<U> make_unique_noinit();
template<typename U> // U is T[]
 unique_ptr<U> make_unique(size_t size);
-

Requires: The expression new U() shall be +

Requires: The expression new T[size]() shall be well-formed.

Effects: Constructs an array of objects of type U and size size via the expression - new U[size]().

+ new T[size]().

template<typename U> // U is T[]
 unique_ptr<U> make_unique_noinit(size_t size);
-

Requires: The expression new U shall be +

Requires: The expression new T[size] shall be well-formed.

Effects: Constructs an array of objects of type U and size size via the expression - new U[size].

+ new T[size].

Examples

For objects with value-initialization.

diff --git a/smart_ptr.htm b/smart_ptr.htm index c16dceb..3956aaf 100644 --- a/smart_ptr.htm +++ b/smart_ptr.htm @@ -62,7 +62,7 @@ described in Bjarne Stroustrup's "The C++ Programming Language", 3rd edition, Section 14.4, Resource Management.

Additionally, the smart pointer library provides efficient factory functions - for creating shared_ptr objects:

+ for creating smart pointer objects:

@@ -137,8 +137,9 @@ throwing exceptions by the common requirements.

History and Acknowledgements

January 2014. Glen Fernandes confined the overloads of make_shared - and allocate_shared for arrays to the specification in N3870 and - implemented make_unique for arrays and objects.

+ and allocate_shared for arrays to the specification in + N3870 + and implemented make_unique for arrays and objects.

November 2012. Glen Fernandes provided implementations of make_shared and allocate_shared for arrays. They achieve a single allocation for an array that can be initialized with constructor arguments or initializer lists From 72e5fb6fd704ba5ad77c76ae4b5b6a3eba559839 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Wed, 29 Jan 2014 16:33:32 -0800 Subject: [PATCH 18/39] Add fourth form of make_unique for objects To support initialization syntax that Args&&... cannot forward perfectly. --- .../boost/smart_ptr/make_unique_object.hpp | 7 +++ make_unique.html | 36 +++++++++---- test/Jamfile.v2 | 1 + test/make_unique_args_test.cpp | 18 +++---- test/make_unique_array_noinit_test.cpp | 13 +---- test/make_unique_noinit_test.cpp | 6 --- test/make_unique_value_test.cpp | 51 +++++++++++++++++++ 7 files changed, 95 insertions(+), 37 deletions(-) create mode 100644 test/make_unique_value_test.cpp diff --git a/include/boost/smart_ptr/make_unique_object.hpp b/include/boost/smart_ptr/make_unique_object.hpp index 3ebdabd..12149c5 100644 --- a/include/boost/smart_ptr/make_unique_object.hpp +++ b/include/boost/smart_ptr/make_unique_object.hpp @@ -11,6 +11,7 @@ #include #include +#include namespace boost { template @@ -27,6 +28,12 @@ namespace boost { } #endif + template + inline typename boost::detail::up_if_not_array::type + make_unique(T&& value) { + return std::unique_ptr(new T(std::move(value))); + } + template inline typename boost::detail::up_if_not_array::type make_unique_noinit() { diff --git a/make_unique.html b/make_unique.html index ab4db62..2d5544d 100644 --- a/make_unique.html +++ b/make_unique.html @@ -26,6 +26,9 @@ unique_ptr<U> make_unique(Args&&... args); #endif + template<typename U> // U is not array + unique_ptr<U> make_unique(U&& value); + template<typename U> // U is not array unique_ptr<U> make_unique_noinit(); @@ -59,6 +62,14 @@ unique_ptr<U> make_unique(Args&&... args); expression new U(forward<Args>(args)...).

template<typename U> // U is not array
+unique_ptr<U> make_unique(U&& value);
+
+

Requires: The expression new U(move(value)) shall + be well-formed.

+

Effects: Constructs an object of type U via the + expression new U(move(value)).

+
+
template<typename U> // U is not array
 unique_ptr<U> make_unique_noinit();

Requires: The expression new U shall be @@ -87,28 +98,33 @@ unique_ptr<U> make_unique_noinit(size_t size);

Examples

For objects with value-initialization.

-
std::unique_ptr<float> p1 = boost::make_unique<float>();
-std::unique_ptr<point> p2 = boost::make_unique<point>();
+
unique_ptr<float> p1 = boost::make_unique<float>();
+unique_ptr<point> p2 = boost::make_unique<point>();

For objects with construction arguments.

-
std::unique_ptr<float> p3 = boost::make_unique<float>(1.5);
-std::unique_ptr<point> p4 = boost::make_unique<point>(x, y);
+
unique_ptr<float> p3 = boost::make_unique<float>(1.0f);
+unique_ptr<point> p4 = boost::make_unique<point>(x, y);
+
+

For objects with given value.

+
+
unique_ptr<string> p4 = boost::make_unique<string>({'a', 'b'});
+unique_ptr<type>   p5 = boost::make_unique<type>({3, 5, 4});

For objects with default-initialization.

-
std::unique_ptr<float> p4 = boost::make_unique_noinit<float>();
-std::unique_ptr<point> p5 = boost::make_unique_noinit<point>();
+
unique_ptr<float> p6 = boost::make_unique_noinit<float>();
+unique_ptr<point> p7 = boost::make_unique_noinit<point>();

For arrays with value-initialization.

-
std::unique_ptr<double[]> a1 = boost::make_unique<double[]>();
-std::unique_ptr<int[][4]> a2 = boost::make_unique<int[][4]>();
+
unique_ptr<double[]> a1 = boost::make_unique<double[]>();
+unique_ptr<int[][4]> a2 = boost::make_unique<int[][4]>();

For arrays with default-initialization.

-
std::unique_ptr<double[]> a3 = boost::make_unique_noinit<double[]>();
-std::unique_ptr<int[][4]> a4 = boost::make_unique_noinit<int[][4]>();
+
unique_ptr<double[]> a3 = boost::make_unique_noinit<double[]>();
+unique_ptr<int[][4]> a4 = boost::make_unique_noinit<int[][4]>();

History

January 2014. Glen Fernandes contributed implementations of diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 6cb4243..09263d3 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -151,6 +151,7 @@ import testing ; [ run make_unique_test.cpp ] [ run make_unique_args_test.cpp ] + [ run make_unique_value_test.cpp ] [ run make_unique_noinit_test.cpp ] [ run make_unique_throws_test.cpp ] [ run make_unique_array_test.cpp ] diff --git a/test/make_unique_args_test.cpp b/test/make_unique_args_test.cpp index d502b30..769c887 100644 --- a/test/make_unique_args_test.cpp +++ b/test/make_unique_args_test.cpp @@ -53,7 +53,7 @@ int main() { #if !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) { - std::unique_ptr a1 = boost::make_unique(1); + std::unique_ptr a1 = boost::make_unique(1); BOOST_TEST(a1.get() != 0); BOOST_TEST(type::instances == 1); BOOST_TEST(a1->sum == 1); @@ -62,7 +62,7 @@ int main() { } { - std::unique_ptr a1 = boost::make_unique(1, 2); + std::unique_ptr a1 = boost::make_unique(1, 2); BOOST_TEST(a1.get() != 0); BOOST_TEST(type::instances == 1); BOOST_TEST(a1->sum == 1 + 2); @@ -71,7 +71,7 @@ int main() { } { - std::unique_ptr a1 = boost::make_unique(1, 2, 3); + std::unique_ptr a1 = boost::make_unique(1, 2, 3); BOOST_TEST(a1.get() != 0); BOOST_TEST(type::instances == 1); BOOST_TEST(a1->sum == 1 + 2 + 3); @@ -80,7 +80,7 @@ int main() { } { - std::unique_ptr a1 = boost::make_unique(1, 2, 3, 4); + std::unique_ptr a1 = boost::make_unique(1, 2, 3, 4); BOOST_TEST(a1.get() != 0); BOOST_TEST(type::instances == 1); BOOST_TEST(a1->sum == 1 + 2 + 3 + 4); @@ -89,7 +89,7 @@ int main() { } { - std::unique_ptr a1 = boost::make_unique(1, 2, 3, 4, 5); + std::unique_ptr a1 = boost::make_unique(1, 2, 3, 4, 5); BOOST_TEST(a1.get() != 0); BOOST_TEST(type::instances == 1); BOOST_TEST(a1->sum == 1 + 2 + 3 + 4 + 5); @@ -98,7 +98,7 @@ int main() { } { - std::unique_ptr a1 = boost::make_unique(1, 2, 3, 4, 5, 6); + std::unique_ptr a1 = boost::make_unique(1, 2, 3, 4, 5, 6); BOOST_TEST(a1.get() != 0); BOOST_TEST(type::instances == 1); BOOST_TEST(a1->sum == 1 + 2 + 3 + 4 + 5 + 6); @@ -107,7 +107,7 @@ int main() { } { - std::unique_ptr a1 = boost::make_unique(1, 2, 3, 4, 5, 6, 7); + std::unique_ptr a1 = boost::make_unique(1, 2, 3, 4, 5, 6, 7); BOOST_TEST(a1.get() != 0); BOOST_TEST(type::instances == 1); BOOST_TEST(a1->sum == 1 + 2 + 3 + 4 + 5 + 6 + 7); @@ -116,7 +116,7 @@ int main() { } { - std::unique_ptr a1 = boost::make_unique(1, 2, 3, 4, 5, 6, 7, 8); + std::unique_ptr a1 = boost::make_unique(1, 2, 3, 4, 5, 6, 7, 8); BOOST_TEST(a1.get() != 0); BOOST_TEST(type::instances == 1); BOOST_TEST(a1->sum == 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8); @@ -125,7 +125,7 @@ int main() { } { - std::unique_ptr a1 = boost::make_unique(1, 2, 3, 4, 5, 6, 7, 8, 9); + std::unique_ptr a1 = boost::make_unique(1, 2, 3, 4, 5, 6, 7, 8, 9); BOOST_TEST(a1.get() != 0); BOOST_TEST(type::instances == 1); BOOST_TEST(a1->sum == 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9); diff --git a/test/make_unique_array_noinit_test.cpp b/test/make_unique_array_noinit_test.cpp index 68b6056..7f85f24 100644 --- a/test/make_unique_array_noinit_test.cpp +++ b/test/make_unique_array_noinit_test.cpp @@ -40,17 +40,7 @@ int main() { std::unique_ptr a1 = boost::make_unique_noinit(2); BOOST_TEST(a1.get() != 0); } - - { - std::unique_ptr a1 = boost::make_unique_noinit(3); - BOOST_TEST(a1.get() != 0); - } - - { - std::unique_ptr a1 = boost::make_unique_noinit(2); - BOOST_TEST(a1.get() != 0); - } - + BOOST_TEST(type::instances == 0); { std::unique_ptr a1 = boost::make_unique_noinit(3); @@ -72,7 +62,6 @@ int main() { BOOST_TEST(type::instances == 0); { std::unique_ptr a1 = boost::make_unique_noinit(3); - const type* a2 = a1.get(); BOOST_TEST(a1.get() != 0); BOOST_TEST(type::instances == 3); a1.reset(); diff --git a/test/make_unique_noinit_test.cpp b/test/make_unique_noinit_test.cpp index 406c958..66026ac 100644 --- a/test/make_unique_noinit_test.cpp +++ b/test/make_unique_noinit_test.cpp @@ -35,11 +35,6 @@ int main() { BOOST_TEST(a1.get() != 0); } - { - std::unique_ptr a1 = boost::make_unique_noinit(); - BOOST_TEST(a1.get() != 0); - } - BOOST_TEST(type::instances == 0); { std::unique_ptr a1 = boost::make_unique_noinit(); @@ -52,7 +47,6 @@ int main() { BOOST_TEST(type::instances == 0); { std::unique_ptr a1 = boost::make_unique_noinit(); - const type* a2 = a1.get(); BOOST_TEST(a1.get() != 0); BOOST_TEST(type::instances == 1); a1.reset(); diff --git a/test/make_unique_value_test.cpp b/test/make_unique_value_test.cpp new file mode 100644 index 0000000..308d488 --- /dev/null +++ b/test/make_unique_value_test.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2014 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include + +struct type { + int x; + int y; +}; + +int main() { +#if !defined(BOOST_NO_CXX11_SMART_PTR) + { + std::unique_ptr a1 = boost::make_unique(); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1->x == 0); + BOOST_TEST(a1->y == 0); + } + + { + std::unique_ptr a1 = boost::make_unique(); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1->x == 0); + BOOST_TEST(a1->y == 0); + } + +#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) + { + std::unique_ptr a1 = boost::make_unique({ 1, 2 }); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1->x == 1); + BOOST_TEST(a1->y == 2); + } + + { + std::unique_ptr a1 = boost::make_unique({ 1, 2 }); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1->x == 1); + BOOST_TEST(a1->y == 2); + } +#endif +#endif + + return boost::report_errors(); +} From aede0039bfa7d37612a2e080fab845008318aabf Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Fri, 31 Jan 2014 11:01:37 -0800 Subject: [PATCH 19/39] make_unique tests run only for C++11 compilers --- test/make_unique_args_test.cpp | 11 +++++++++-- test/make_unique_array_noinit_test.cpp | 10 ++++++++-- test/make_unique_array_test.cpp | 10 ++++++++-- test/make_unique_array_throws_test.cpp | 10 ++++++++-- test/make_unique_noinit_test.cpp | 11 +++++++++-- test/make_unique_test.cpp | 11 +++++++++-- test/make_unique_throws_test.cpp | 11 +++++++++-- test/make_unique_value_test.cpp | 11 +++++++++-- 8 files changed, 69 insertions(+), 16 deletions(-) diff --git a/test/make_unique_args_test.cpp b/test/make_unique_args_test.cpp index 769c887..6c13d41 100644 --- a/test/make_unique_args_test.cpp +++ b/test/make_unique_args_test.cpp @@ -6,6 +6,8 @@ * Version 1.0. (See accompanying file LICENSE_1_0.txt * or copy at http://boost.org/LICENSE_1_0.txt) */ +#include +#if !defined(BOOST_NO_CXX11_SMART_PTR) #include #include @@ -40,7 +42,6 @@ private: unsigned int type::instances = 0; int main() { -#if !defined(BOOST_NO_CXX11_SMART_PTR) BOOST_TEST(type::instances == 0); { std::unique_ptr a1 = boost::make_unique(); @@ -132,8 +133,14 @@ int main() { a1.reset(); BOOST_TEST(type::instances == 0); } -#endif #endif return boost::report_errors(); } +#else + +int main() { + return 0; +} + +#endif diff --git a/test/make_unique_array_noinit_test.cpp b/test/make_unique_array_noinit_test.cpp index 7f85f24..edaa67f 100644 --- a/test/make_unique_array_noinit_test.cpp +++ b/test/make_unique_array_noinit_test.cpp @@ -7,6 +7,7 @@ * or copy at http://boost.org/LICENSE_1_0.txt) */ #include +#if !defined(BOOST_NO_CXX11_SMART_PTR) #include #include @@ -30,7 +31,6 @@ private: unsigned int type::instances = 0; int main() { -#if !defined(BOOST_NO_CXX11_SMART_PTR) { std::unique_ptr a1 = boost::make_unique_noinit(3); BOOST_TEST(a1.get() != 0); @@ -76,7 +76,13 @@ int main() { a1.reset(); BOOST_TEST(type::instances == 0); } -#endif return boost::report_errors(); } +#else + +int main() { + return 0; +} + +#endif diff --git a/test/make_unique_array_test.cpp b/test/make_unique_array_test.cpp index 21808af..8e5ea79 100644 --- a/test/make_unique_array_test.cpp +++ b/test/make_unique_array_test.cpp @@ -7,6 +7,7 @@ * or copy at http://boost.org/LICENSE_1_0.txt) */ #include +#if !defined(BOOST_NO_CXX11_SMART_PTR) #include #include @@ -30,7 +31,6 @@ private: unsigned int type::instances = 0; int main() { -#if !defined(BOOST_NO_CXX11_SMART_PTR) { std::unique_ptr a1 = boost::make_unique(3); BOOST_TEST(a1.get() != 0); @@ -100,7 +100,13 @@ int main() { a1.reset(); BOOST_TEST(type::instances == 0); } -#endif return boost::report_errors(); } +#else + +int main() { + return 0; +} + +#endif diff --git a/test/make_unique_array_throws_test.cpp b/test/make_unique_array_throws_test.cpp index dc48fa1..3efbc2a 100644 --- a/test/make_unique_array_throws_test.cpp +++ b/test/make_unique_array_throws_test.cpp @@ -7,6 +7,7 @@ * or copy at http://boost.org/LICENSE_1_0.txt) */ #include +#if !defined(BOOST_NO_CXX11_SMART_PTR) #include #include @@ -33,7 +34,6 @@ private: unsigned int type::instances = 0; int main() { -#if !defined(BOOST_NO_CXX11_SMART_PTR) BOOST_TEST(type::instances == 0); try { boost::make_unique(6); @@ -65,7 +65,13 @@ int main() { } catch (...) { BOOST_TEST(type::instances == 0); } -#endif return boost::report_errors(); } +#else + +int main() { + return 0; +} + +#endif diff --git a/test/make_unique_noinit_test.cpp b/test/make_unique_noinit_test.cpp index 66026ac..1ef0daa 100644 --- a/test/make_unique_noinit_test.cpp +++ b/test/make_unique_noinit_test.cpp @@ -6,6 +6,8 @@ * Version 1.0. (See accompanying file LICENSE_1_0.txt * or copy at http://boost.org/LICENSE_1_0.txt) */ +#include +#if !defined(BOOST_NO_CXX11_SMART_PTR) #include #include @@ -29,7 +31,6 @@ private: unsigned int type::instances = 0; int main() { -#if !defined(BOOST_NO_CXX11_SMART_PTR) { std::unique_ptr a1 = boost::make_unique_noinit(); BOOST_TEST(a1.get() != 0); @@ -52,7 +53,13 @@ int main() { a1.reset(); BOOST_TEST(type::instances == 0); } -#endif return boost::report_errors(); } +#else + +int main() { + return 0; +} + +#endif diff --git a/test/make_unique_test.cpp b/test/make_unique_test.cpp index 6106ac3..ab13c33 100644 --- a/test/make_unique_test.cpp +++ b/test/make_unique_test.cpp @@ -6,6 +6,8 @@ * Version 1.0. (See accompanying file LICENSE_1_0.txt * or copy at http://boost.org/LICENSE_1_0.txt) */ +#include +#if !defined(BOOST_NO_CXX11_SMART_PTR) #include #include @@ -29,7 +31,6 @@ private: unsigned int type::instances = 0; int main() { -#if !defined(BOOST_NO_CXX11_SMART_PTR) { std::unique_ptr a1 = boost::make_unique(); BOOST_TEST(a1.get() != 0); @@ -59,7 +60,13 @@ int main() { a1.reset(); BOOST_TEST(type::instances == 0); } -#endif return boost::report_errors(); } +#else + +int main() { + return 0; +} + +#endif diff --git a/test/make_unique_throws_test.cpp b/test/make_unique_throws_test.cpp index bf9e5bf..9594c90 100644 --- a/test/make_unique_throws_test.cpp +++ b/test/make_unique_throws_test.cpp @@ -6,6 +6,8 @@ * Version 1.0. (See accompanying file LICENSE_1_0.txt * or copy at http://boost.org/LICENSE_1_0.txt) */ +#include +#if !defined(BOOST_NO_CXX11_SMART_PTR) #include #include @@ -32,7 +34,6 @@ private: unsigned int type::instances = 0; int main() { -#if !defined(BOOST_NO_CXX11_SMART_PTR) BOOST_TEST(type::instances == 0); try { boost::make_unique(); @@ -40,7 +41,13 @@ int main() { } catch (...) { BOOST_TEST(type::instances == 0); } -#endif return boost::report_errors(); } +#else + +int main() { + return 0; +} + +#endif diff --git a/test/make_unique_value_test.cpp b/test/make_unique_value_test.cpp index 308d488..03cdf47 100644 --- a/test/make_unique_value_test.cpp +++ b/test/make_unique_value_test.cpp @@ -6,6 +6,8 @@ * Version 1.0. (See accompanying file LICENSE_1_0.txt * or copy at http://boost.org/LICENSE_1_0.txt) */ +#include +#if !defined(BOOST_NO_CXX11_SMART_PTR) #include #include @@ -15,7 +17,6 @@ struct type { }; int main() { -#if !defined(BOOST_NO_CXX11_SMART_PTR) { std::unique_ptr a1 = boost::make_unique(); BOOST_TEST(a1.get() != 0); @@ -44,8 +45,14 @@ int main() { BOOST_TEST(a1->x == 1); BOOST_TEST(a1->y == 2); } -#endif #endif return boost::report_errors(); } +#else + +int main() { + return 0; +} + +#endif From 63a05a3576e55d046a28ccfe1b4e0949cdb0f3dc Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Sun, 2 Feb 2014 22:00:08 -0800 Subject: [PATCH 20/39] Refactor make_array_helper and array_deleter Reduce the amount of code in allocate_array_helper, make_array_helper, and array_deleter using the empty base class optimization technique. --- .../boost/smart_ptr/allocate_shared_array.hpp | 1 - .../detail/allocate_array_helper.hpp | 154 ++++-------------- .../boost/smart_ptr/detail/array_deleter.hpp | 84 ++++------ .../smart_ptr/detail/array_size_base.hpp | 37 +++++ .../smart_ptr/detail/make_array_helper.hpp | 136 ++++------------ 5 files changed, 135 insertions(+), 277 deletions(-) create mode 100644 include/boost/smart_ptr/detail/array_size_base.hpp diff --git a/include/boost/smart_ptr/allocate_shared_array.hpp b/include/boost/smart_ptr/allocate_shared_array.hpp index 905d311..bac8cef 100644 --- a/include/boost/smart_ptr/allocate_shared_array.hpp +++ b/include/boost/smart_ptr/allocate_shared_array.hpp @@ -11,7 +11,6 @@ #include #include -#include #include #include diff --git a/include/boost/smart_ptr/detail/allocate_array_helper.hpp b/include/boost/smart_ptr/detail/allocate_array_helper.hpp index 1f358e7..de43c76 100644 --- a/include/boost/smart_ptr/detail/allocate_array_helper.hpp +++ b/include/boost/smart_ptr/detail/allocate_array_helper.hpp @@ -9,45 +9,53 @@ #ifndef BOOST_SMART_PTR_DETAIL_ALLOCATE_ARRAY_HELPER_HPP #define BOOST_SMART_PTR_DETAIL_ALLOCATE_ARRAY_HELPER_HPP +#include +#include #include namespace boost { namespace detail { template - class allocate_array_helper; + class allocate_array_helper + : array_size_base { + using array_size_base::size; - template - class allocate_array_helper { - template + template friend class allocate_array_helper; typedef typename A::template rebind ::other A2; - typedef typename A::template rebind::other A3; + typedef typename A::template rebind::other A3; public: - typedef typename A2::value_type value_type; - typedef typename A2::pointer pointer; - typedef typename A2::const_pointer const_pointer; - typedef typename A2::reference reference; + typedef typename array_inner::type type; + typedef typename A2::value_type value_type; + typedef typename A2::pointer pointer; + typedef typename A2::const_pointer const_pointer; + typedef typename A2::reference reference; typedef typename A2::const_reference const_reference; - typedef typename A2::size_type size_type; + typedef typename A2::size_type size_type; typedef typename A2::difference_type difference_type; template struct rebind { - typedef allocate_array_helper other; + typedef allocate_array_helper other; }; - allocate_array_helper(const A& allocator_, std::size_t size_, T** data_) + allocate_array_helper(const A& allocator_, type** data_) : allocator(allocator_), - size(sizeof(T) * size_), + data(data_) { + } + + allocate_array_helper(const A& allocator_, std::size_t size_, type** data_) + : array_size_base(size_), + allocator(allocator_), data(data_) { } template - allocate_array_helper(const allocate_array_helper& other) - : allocator(other.allocator), - size(other.size), + allocate_array_helper(const allocate_array_helper& other) + : array_size_base(other), + allocator(other.allocator), data(other.data) { } @@ -64,22 +72,22 @@ namespace boost { } pointer allocate(size_type count, const void* value = 0) { - std::size_t a1 = boost::alignment_of::value; + std::size_t a1 = boost::alignment_of::value; std::size_t n1 = count * sizeof(Y) + a1 - 1; - char* p1 = A3(allocator).allocate(n1 + size, value); - char* p2 = p1 + n1; + char* p1 = A3(allocator).allocate(size + n1, value); + char* p2 = p1 + n1; while (std::size_t(p2) % a1 != 0) { p2--; } - *data = reinterpret_cast(p2); - return reinterpret_cast(p1); + *data = reinterpret_cast(p2); + return reinterpret_cast(p1); } void deallocate(pointer memory, size_type count) { - std::size_t a1 = boost::alignment_of::value; + std::size_t a1 = boost::alignment_of::value; std::size_t n1 = count * sizeof(Y) + a1 - 1; - char* p1 = reinterpret_cast(memory); - A3(allocator).deallocate(p1, n1 + size); + char* p1 = reinterpret_cast(memory); + A3(allocator).deallocate(p1, size + n1); } void construct(pointer memory, const Y& value) { @@ -91,110 +99,18 @@ namespace boost { } template - bool operator==(const allocate_array_helper& other) const { + bool operator==(const allocate_array_helper& other) const { return allocator == other.allocator; } template - bool operator!=(const allocate_array_helper& other) const { + bool operator!=(const allocate_array_helper& other) const { return !(*this == other); } private: A2 allocator; - std::size_t size; - T** data; - }; - - template - class allocate_array_helper { - template - friend class allocate_array_helper; - - typedef typename A::template rebind ::other A2; - typedef typename A::template rebind::other A3; - - public: - typedef typename A2::value_type value_type; - typedef typename A2::pointer pointer; - typedef typename A2::const_pointer const_pointer; - typedef typename A2::reference reference; - typedef typename A2::const_reference const_reference; - typedef typename A2::size_type size_type; - typedef typename A2::difference_type difference_type; - - template - struct rebind { - typedef allocate_array_helper other; - }; - - allocate_array_helper(const A& allocator_, T** data_) - : allocator(allocator_), - data(data_) { - } - - template - allocate_array_helper(const allocate_array_helper& other) - : allocator(other.allocator), - data(other.data) { - } - - pointer address(reference value) const { - return allocator.address(value); - } - - const_pointer address(const_reference value) const { - return allocator.address(value); - } - - size_type max_size() const { - return allocator.max_size(); - } - - pointer allocate(size_type count, const void* value = 0) { - std::size_t a1 = boost::alignment_of::value; - std::size_t n1 = count * sizeof(Y) + a1 - 1; - char* p1 = A3(allocator).allocate(n1 + N1, value); - char* p2 = p1 + n1; - while (std::size_t(p2) % a1 != 0) { - p2--; - } - *data = reinterpret_cast(p2); - return reinterpret_cast(p1); - } - - void deallocate(pointer memory, size_type count) { - std::size_t a1 = boost::alignment_of::value; - std::size_t n1 = count * sizeof(Y) + a1 - 1; - char* p1 = reinterpret_cast(memory); - A3(allocator).deallocate(p1, n1 + N1); - } - - void construct(pointer memory, const Y& value) { - allocator.construct(memory, value); - } - - void destroy(pointer memory) { - allocator.destroy(memory); - } - - template - bool operator==(const allocate_array_helper& other) const { - return allocator == other.allocator; - } - - template - bool operator!=(const allocate_array_helper& other) const { - return !(*this == other); - } - - private: - enum { - N1 = N * sizeof(T) - }; - - A2 allocator; - T** data; + type** data; }; } } diff --git a/include/boost/smart_ptr/detail/array_deleter.hpp b/include/boost/smart_ptr/detail/array_deleter.hpp index 9d7f970..58adbbc 100644 --- a/include/boost/smart_ptr/detail/array_deleter.hpp +++ b/include/boost/smart_ptr/detail/array_deleter.hpp @@ -15,13 +15,38 @@ namespace boost { namespace detail { template - class array_deleter; + struct array_count_base; template - class array_deleter { + struct array_count_base { + array_count_base(std::size_t size_) + : size(size_) { + } + + std::size_t size; + }; + + template + struct array_count_base { + enum { + size = N + }; + }; + + template + class array_deleter + : array_count_base { + using array_count_base::size; + public: + typedef typename array_inner::type type; + + array_deleter() + : object(0) { + } + array_deleter(std::size_t size_) - : size(size_), + : array_count_base(size_), object(0) { } @@ -31,18 +56,18 @@ namespace boost { } } - void init(T* memory) { + void init(type* memory) { array_init(memory, size); object = memory; } template - void init(T* memory, const T* value) { - array_init(memory, size, value); + void init(type* memory, const type* value) { + array_init(memory, size, value); object = memory; } - void noinit(T* memory) { + void noinit(type* memory) { array_noinit(memory, size); object = memory; } @@ -55,49 +80,8 @@ namespace boost { } private: - std::size_t size; - T* object; - }; - - template - class array_deleter { - public: - array_deleter() - : object(0) { - } - - ~array_deleter() { - if (object) { - array_destroy(object, N); - } - } - - void init(T* memory) { - array_init(memory, N); - object = memory; - } - - template - void init(T* memory, const T* value) { - array_init(memory, N, value); - object = memory; - } - - void noinit(T* memory) { - array_noinit(memory, N); - object = memory; - } - - void operator()(const void*) { - if (object) { - array_destroy(object, N); - object = 0; - } - } - - private: - T* object; - }; + type* object; + }; } } diff --git a/include/boost/smart_ptr/detail/array_size_base.hpp b/include/boost/smart_ptr/detail/array_size_base.hpp new file mode 100644 index 0000000..df5aab2 --- /dev/null +++ b/include/boost/smart_ptr/detail/array_size_base.hpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#ifndef BOOST_SMART_PTR_DETAIL_ARRAY_SIZE_BASE_HPP +#define BOOST_SMART_PTR_DETAIL_ARRAY_SIZE_BASE_HPP + +#include + +namespace boost { + namespace detail { + template + struct array_size_base; + + template + struct array_size_base { + array_size_base(std::size_t size_) + : size(size_ * sizeof(T)) { + } + + std::size_t size; + }; + + template + struct array_size_base { + enum { + size = N * sizeof(T) + }; + }; + } +} + +#endif diff --git a/include/boost/smart_ptr/detail/make_array_helper.hpp b/include/boost/smart_ptr/detail/make_array_helper.hpp index cc1fc44..3aebb6d 100644 --- a/include/boost/smart_ptr/detail/make_array_helper.hpp +++ b/include/boost/smart_ptr/detail/make_array_helper.hpp @@ -9,40 +9,47 @@ #ifndef BOOST_SMART_PTR_DETAIL_MAKE_ARRAY_HELPER_HPP #define BOOST_SMART_PTR_DETAIL_MAKE_ARRAY_HELPER_HPP +#include +#include #include namespace boost { namespace detail { template - class make_array_helper; + class make_array_helper + : array_size_base { + using array_size_base::size; - template - class make_array_helper { template friend class make_array_helper; public: - typedef Y value_type; - typedef Y* pointer; - typedef const Y* const_pointer; - typedef Y& reference; - typedef const Y& const_reference; + typedef typename array_inner::type type; + typedef Y value_type; + typedef Y* pointer; + typedef const Y* const_pointer; + typedef Y& reference; + typedef const Y& const_reference; typedef std::size_t size_type; - typedef ptrdiff_t difference_type; + typedef ptrdiff_t difference_type; template struct rebind { - typedef make_array_helper other; + typedef make_array_helper other; }; - make_array_helper(std::size_t size_, T** data_) - : size(sizeof(T) * size_), + make_array_helper(type** data_) + : data(data_) { + } + + make_array_helper(std::size_t size_, type** data_) + : array_size_base(size_), data(data_) { } template - make_array_helper(const make_array_helper& other) - : size(other.size), + make_array_helper(const make_array_helper& other) + : array_size_base(other), data(other.data) { } @@ -59,15 +66,15 @@ namespace boost { } pointer allocate(size_type count, const void* = 0) { - std::size_t a1 = boost::alignment_of::value; + std::size_t a1 = boost::alignment_of::value; std::size_t n1 = count * sizeof(Y) + a1 - 1; - void* p1 = ::operator new(n1 + size); - char* p2 = static_cast(p1) + n1; + void* p1 = ::operator new(n1 + size); + char* p2 = static_cast(p1) + n1; while (std::size_t(p2) % a1 != 0) { p2--; } - *data = reinterpret_cast(p2); - return reinterpret_cast(p1); + *data = reinterpret_cast(p2); + return reinterpret_cast(p1); } void deallocate(pointer memory, size_type) { @@ -85,102 +92,17 @@ namespace boost { } template - bool operator==(const make_array_helper&) const { + bool operator==(const make_array_helper&) const { return true; } template - bool operator!=(const make_array_helper& other) const { + bool operator!=(const make_array_helper& other) const { return !(*this == other); } private: - std::size_t size; - T** data; - }; - - template - class make_array_helper { - template - friend class make_array_helper; - - public: - typedef Y value_type; - typedef Y* pointer; - typedef const Y* const_pointer; - typedef Y& reference; - typedef const Y& const_reference; - typedef std::size_t size_type; - typedef ptrdiff_t difference_type; - - template - struct rebind { - typedef make_array_helper other; - }; - - make_array_helper(T** data_) - : data(data_) { - } - - template - make_array_helper(const make_array_helper& other) - : data(other.data) { - } - - pointer address(reference value) const { - return &value; - } - - const_pointer address(const_reference value) const { - return &value; - } - - size_type max_size() const { - return static_cast(-1) / sizeof(Y); - } - - pointer allocate(size_type count, const void* = 0) { - std::size_t a1 = boost::alignment_of::value; - std::size_t n1 = count * sizeof(Y) + a1 - 1; - void* p1 = ::operator new(n1 + N1); - char* p2 = static_cast(p1) + n1; - while (std::size_t(p2) % a1 != 0) { - p2--; - } - *data = reinterpret_cast(p2); - return reinterpret_cast(p1); - } - - void deallocate(pointer memory, size_type) { - void* p1 = memory; - ::operator delete(p1); - } - - void construct(pointer memory, const Y& value) { - void* p1 = memory; - ::new(p1) Y(value); - } - - void destroy(pointer memory) { - memory->~Y(); - } - - template - bool operator==(const make_array_helper&) const { - return true; - } - - template - bool operator!=(const make_array_helper& other) const { - return !(*this == other); - } - - private: - enum { - N1 = N * sizeof(T) - }; - - T** data; + type** data; }; } } From 2b033ce05db9558fcb4971afc85dbc7dd6cdb42d Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Mon, 3 Feb 2014 16:42:57 -0800 Subject: [PATCH 21/39] Improve documentation for make_shared for arrays --- make_shared_array.html | 264 +++++++++++++++++++++++++++-------------- make_unique.html | 168 +++++++++++++++----------- 2 files changed, 272 insertions(+), 160 deletions(-) diff --git a/make_shared_array.html b/make_shared_array.html index e7d80d4..76e4f20 100644 --- a/make_shared_array.html +++ b/make_shared_array.html @@ -8,13 +8,13 @@

boost.png (6897 bytes)make_shared and allocate_shared for arrays

-

Introduction
- Synopsis
+

Introduction
+ Synopsis
+ Common Requirements
Free Functions
- Examples
History
References

-

Introduction

+

Introduction

Originally the Boost function templates make_shared and allocate_shared were for efficient allocation of shared objects only. There was a need to have efficient allocation of @@ -28,24 +28,24 @@ make_shared uses the global operator new to allocate memory, whereas allocate_shared uses an user-supplied allocator, allowing finer control.

-

Synopsis

+

Synopsis

namespace boost {
     template<typename U> // U is T[]
     shared_ptr<U> make_shared(size_t size);
 
     template<typename U, typename A> // U is T[]
     shared_ptr<U> allocate_shared(const A& allocator, size_t size);
-    
+
     template<typename U> // U is T[N]
     shared_ptr<U> make_shared();
 
     template<typename U, typename A> // U is T[N]
     shared_ptr<U> allocate_shared(const A& allocator);
-   
+
     template<typename U> // U is T[]
     shared_ptr<U> make_shared(size_t size, const T& value);
 
-    template<typename U, typename A> // U is T[]
+    template<typename U, typename A>  // U is T[]
     shared_ptr<U> allocate_shared(const A& allocator, size_t size, const T& value);
 
     template<typename U> // U is T[N]
@@ -66,95 +66,183 @@
     template<typename U, typename A> // U is T[N]
     shared_ptr<U> allocate_shared_noinit(const A& allocator);
 }
-

Free Functions

-
template<typename U> // U is T[]
-shared_ptr<U> make_shared(size_t size);
-
-template<typename U, typename A> // U is T[]
-shared_ptr<U> allocate_shared(const A& allocator, size_t size);
-
-template<typename U> // U is T[N]
-shared_ptr<U> make_shared();
-
-template<typename U, typename A> // U is T[N]
-shared_ptr<U> allocate_shared(const A& allocator);
+

Common Requirements

+
template<typename U>
+    shared_ptr<U> make_shared(args);
+template<typename U, typename A>
+    shared_ptr<U> allocate_shared(const A& allocator, args);
+template<typename U>
+    shared_ptr<U> make_shared_noinit(args);
+template<typename U, typename A>
+    shared_ptr<U> allocate_shared_noinit(const A& allocator, args);
-

Requires: The expression - new(pointer) T(), where pointer is a - void* pointing to storage suitable to hold an object of - type T, shall be well-formed. A shall be an - Allocator, as described in section 20.1.5 (Allocator - requirements) of the C++ Standard. The copy constructor and - destructor of A shall not throw.

-

Effects: Allocates memory suitable for an array of type - T and size size and constructs an array of - objects in it via the placement new expression new(pointer) - T(). allocate_shared uses a copy of - allocator to allocate memory. If an exception is thrown, - has no effect.

+

Requires: U is of the form T[] or + T[N]. A shall be an Allocator, as + described in section 17.6.3.5 [Allocator + requirements] of the C++ Standard. The copy constructor and + destructor of A shall not throw exceptions.

+

Effects: Allocates memory for an object of type U + (or T[size] when U is T[], + where size is determined from args + as specified by the concrete overload). The object is initialized as + specified by the concrete overload. The templates + allocate_shared and allocate_shared_noinit + use a copy of allocator to allocate memory. If an + exception is thrown, the functions have no effect.

Returns: A shared_ptr instance that stores and - owns the address of the newly constructed array of type T - and size size.

-

Postconditions: - get() != 0 && use_count() == 1.

-

Throws: bad_alloc, or an exception thrown from - A::allocate or the constructor of T.

-

Notes: This implementation allocates the memory required for - the returned shared_ptr and an array of type - T of size size in a single allocation. This - provides efficiency to equivalent to an intrusive smart pointer.

-
-
template<typename U> // U is T[]
-shared_ptr<U> make_shared(size_t size, const T& value);
-
-template<typename U, typename A> // U is T[]
-shared_ptr<U> allocate_shared(const A& allocator, size_t size, const T& value);
-
-template<typename U> // U is T[N]
-shared_ptr<U> make_shared(const T& value);
-
-template<typename U, typename A> // U is T[N]
-shared_ptr<U> allocate_shared(const A& allocator, const T& value);
-
-

Notes: These overloads initialize array objects with the given + owns the address of the newly constructed object.

+

Postconditions: r.get() != 0 && + r.use_count() == 1, where r is the return value.

+

Throws: bad_alloc, an exception thrown from + A::allocate, or from the initialization of the + object.

-
template<typename U> // U is T[]
-shared_ptr<U> make_shared_noinit(size_t size);
-
-template<typename U, typename A> // U is T[]
-shared_ptr<U> allocate_shared_noinit(const A& allocator, size_t size);
-
-template<typename U> // U is T[N]
-shared_ptr<U> make_shared_noinit();
-
-template<typename U, typename A> // U is T[N]
-shared_ptr<U> allocate_shared_noinit(const A& allocator);
-

Notes: These overloads do not perform value initialization of - array objects.

-
-

Examples

-

The following examples value-initialize objects.

-
-
boost::shared_ptr<int[]>     a1  = boost::make_shared<int[]>(size);
-boost::shared_ptr<int[8]>    a2  = boost::make_shared<int[8]>();
-boost::shared_ptr<int[][2]>  a3  = boost::make_shared<int[][2]>(size);
-boost::shared_ptr<int[4][2]> a4  = boost::make_shared<int[4][2]>();
+

Remarks:

+
+

This implementation performs no more than one memory + allocation. This provides efficiency to equivalent to an intrusive + smart pointer.

+

When an object of an array type T is specified to be + initialized to a value of the same type value, this + shall be interpreted to mean that each array element of the object + is initialized to the corresponding element from + value.

+

When an object of an array type is specified to be + value-initialized, this shall be interpreted to mean that each + array element of the object is value-initialized.

+

Array elements are initialized in ascending order of their + addresses.

+

When a subobject of a non-array type T is specified to + be initialized to a value value, or to + T(list...), where list... is a list of + constructor arguments, make_shared shall perform this + initialization via the expression ::new(ptr) T(value) + or ::new(ptr) T(list...) respectively, where + ptr has type void* and points to storage + suitable to hold an object of type T.

+

When a subobject of non-array type T is specified to + be value-initialized, make_shared shall perform this + initialization via the expression ::new(ptr) T(), where + ptr has type void* and points to storage + suitable to hold an object of type T.

+

When a subobject of non-array type T is specified to + be default-initialized, make_shared_noinit and + allocate_shared_noinit shall perform this + initialization via the expression ::new(ptr) T, where + ptr has type void* and points to storage + suitable to hold an object of type T.

+

When the lifetime of the object managed by the return value ends, + or when the initialization of an array element throws an exception, + the initialized elements should be destroyed in the reverse order + of their construction.

+
-

The following examples initialize objects with a given value.

+

Free Functions

+
template<typename U> 
+    shared_ptr<U> make_shared(size_t size);
+template<typename U, typename A> 
+    shared_ptr<U> allocate_shared(const A& allocator, size_t size);
-
boost::shared_ptr<int[]>     a5  = boost::make_shared<int[]>(size, 1);
-boost::shared_ptr<int[8]>    a6  = boost::make_shared<int[8]>(1);
-boost::shared_ptr<int[][2]>  a7  = boost::make_shared<int[][2]>(size, {1, 2});
-boost::shared_ptr<int[4][2]> a8  = boost::make_shared<int[4][2]>({1, 2});
+

Returns: A shared_ptr to a value-initialized + object of type T[size].

+

Remarks: These overloads shall only participate in overload + resolution when U is of the form T[].

-

The following examples default-initialize objects.

-
boost::shared_ptr<int[]>     a9  = boost::make_shared_noinit<int[]>(size);
-boost::shared_ptr<int[8]>    a10 = boost::make_shared_noinit<int[8]>();
-boost::shared_ptr<int[][2]>  a11 = boost::make_shared_noinit<int[][2]>(size);
-boost::shared_ptr<int[4][2]> a12 = boost::make_shared_noinit<int[4][2]>();
+

Examples:

+
+
boost::shared_ptr<int[]> a1 = boost::make_shared<int[]>(size);
+boost::shared_ptr<int[][2]> a2 = boost::make_shared<int[][2]>(size);
+
+
+
template<typename U> 
+    shared_ptr<U> make_shared();
+template<typename U, typename A> 
+    shared_ptr<U> allocate_shared(const A& allocator);
+
+

Returns: A shared_ptr to a value-initialized + object of type T[N].

+

Remarks: These overloads shall only participate in overload + resolution when U is of the form T[N].

+
+
+

Examples:

+
+
boost::shared_ptr<int[8]> a1 = boost::make_shared<int[8]>();
+boost::shared_ptr<int[4][2]> a2 = boost::make_shared<int[4][2]>();
+
+
+
template<typename U> 
+    shared_ptr<U> make_shared(size_t size, const T& value);
+template<typename U, typename A> 
+    shared_ptr<U> allocate_shared(const A& allocator, size_t size, const T& value);
+
+

Returns: A shared_ptr to an object of type + T[size], where each array element of type T + is initialized to value.

+

Remarks: These overloads shall only participate in overload + resolution when U is of the form T[].

+
+
+

Examples:

+
+
boost::shared_ptr<int[]> a1 = boost::make_shared<int[]>(size, 1);
+boost::shared_ptr<int[][2]> a2 = boost::make_shared<int[][2]>(size, {1, 2});
+
+
+
template<typename U> 
+    shared_ptr<U> make_shared(const T& value);
+template<typename U, typename A> 
+    shared_ptr<U> allocate_shared(const A& allocator, const T& value);
+
+

Returns: A shared_ptr to an object of type + T[N], where each array element of type T is + initialized to value.

+

Remarks: These overloads shall only participate in overload + resolution when U is of the form T[N].

+
+
+

Examples:

+
+
boost::shared_ptr<int[8]> a1 = boost::make_shared<int[8]>(1);
+boost::shared_ptr<int[4][2]> a2 = boost::make_shared<int[4][2]>({1, 2});
+
+
+
template<typename U> 
+    shared_ptr<U> make_shared_noinit(size_t size);
+template<typename U, typename A> 
+    shared_ptr<U> allocate_shared_noinit(const A& allocator, size_t size);
+
+

Returns: A shared_ptr to a default-initialized + object of type T[size].

+

Remarks: These overloads shall only participate in overload + resolution when U is of the form T[].

+
+
+

Examples:

+
+
boost::shared_ptr<int[]> a1 = boost::make_shared_noinit<int[]>(size);
+boost::shared_ptr<int[][2]> a2 = boost::make_shared_noinit<int[][2]>(size);
+
+
+
template<typename U> 
+    shared_ptr<U> make_shared_noinit();
+template<typename U, typename A> 
+    shared_ptr<U> allocate_shared_noinit(const A& allocator);
+
+

Returns: A shared_ptr to a default-initialized + object of type T[N].

+

Remarks: These overloads shall only participate in overload + resolution when U is of the form T[N].

+
+
+

Examples:

+
+
boost::shared_ptr<int[8]> a1 = boost::make_shared_noinit<int[8]>();
+boost::shared_ptr<int[4][2]> a2 = boost::make_shared_noinit<int[4][2]>();
+

History

January 2014. Glen Fernandes reduced the overloads of make_shared and diff --git a/make_unique.html b/make_unique.html index 2d5544d..fc46428 100644 --- a/make_unique.html +++ b/make_unique.html @@ -7,16 +7,16 @@

boost.png (6897 bytes)make_unique

-

Introduction
- Synopsis
+

Introduction
+ Synopsis
+ Common Requirements
Free Functions
- Examples
History

-

Introduction

+

Introduction

The header file <boost/make_unique.hpp> provides overloaded function template make_unique for convenient creation of unique_ptr objects.

-

Synopsis

+

Synopsis

namespace boost {
     template<typename U> // U is not array
     unique_ptr<U> make_unique();
@@ -29,103 +29,127 @@
     template<typename U> // U is not array
     unique_ptr<U> make_unique(U&& value);
 
+    template<typename U> // U is T[]
+    unique_ptr<U> make_unique(size_t size);
+
     template<typename U> // U is not array
     unique_ptr<U> make_unique_noinit();
 
-    template<typename U> // U is T[]
-    unique_ptr<U> make_unique(size_t size);
-
     template<typename U> // U is T[]
     unique_ptr<U> make_unique_noinit(size_t size);
 }
-

Free Functions

-
template<typename U> // U is not array
-unique_ptr<U> make_unique();
+

Common Requirements

+
template<typename U>
+    unique_ptr<U> make_unique(args);
+template<typename U>
+    unique_ptr<U> make_unique_noinit(args);
-

Requires: The expression new U() shall be - well-formed.

-

Effects: Constructs an object of type U via the - expression new U().

+

Effects: Allocates memory for an object of type U + (or T[size] when U is T[], + where size is determined from args as + specified by the concrete overload). The object is initialized from + args as specified by the concrete overload. If an + exception is thrown, the functions have no effect.

Returns: A unique_ptr instance that stores and owns the address of the newly constructed object.

-

Postconditions: get() != 0.

+

Postconditions: r.get() != 0, where + r is the return value.

Throws: bad_alloc, or an exception thrown from - the constructor of U.

+ the initialization of the object.

-
template<typename U, typename... Args> // U is not array
-unique_ptr<U> make_unique(Args&&... args);
-

Requires: The expression - new U(forward<Args>(args)...) shall be - well-formed.

-

Effects: Constructs an object of type U via the - expression new U(forward<Args>(args)...).

+

Remarks:

+
+

When an object of a non-array type T is specified to + be initialized to a value value, or to + T(list...), where list... is a list of + constructor arguments, make_unique shall perform this + initialization via the expression new T(value) or + new T(list...) respectively.

+

When an object of type T is specified to be + value-initialized, make_unique shall perform this + initialization via the expression new T().

+

When an object of type T is specified to be + default-initialized, make_unique_noinit shall perform + this initialization via the expression new T.

+
-
template<typename U> // U is not array
+    

Free Functions

+
template<typename U, typename... Args>
+unique_ptr<U> make_unique(Args&&... args);
+
+

Returns: A unique_ptr to an object of type U, + initialized to U(forward<Args>(args)...).

+

Remarks: This overload shall only participate in overload + resolution when U is not an array type.

+
+
+

Examples:

+
+
unique_ptr<float> p1 = boost::make_unique<float>();
+unique_ptr<point> p2 = boost::make_unique<point>(x, y);
+
+
+
template<typename U>
 unique_ptr<U> make_unique(U&& value);
-

Requires: The expression new U(move(value)) shall - be well-formed.

-

Effects: Constructs an object of type U via the - expression new U(move(value)).

+

Returns: A unique_ptr to an object of type U, + initialized to move(value).

+

Remarks: This overload shall only participate in overload + resolution when U is not an array type.

-
template<typename U> // U is not array
-unique_ptr<U> make_unique_noinit();
-

Requires: The expression new U shall be - well-formed.

-

Effects: Constructs an object of type U via the - expression new U.

+

Examples:

+
+
unique_ptr<string> p1 = boost::make_unique<string>({'a', 'b'});
+unique_ptr<point> p2 = boost::make_unique<point>({-10, 25});
+
-
template<typename U> // U is T[]
-unique_ptr<U> make_unique(size_t size);
+
template<typename U>
+unique_ptr<U> make_unique(size_t size);
-

Requires: The expression new T[size]() shall be - well-formed.

-

Effects: Constructs an array of objects of type - U and size size via the expression - new T[size]().

+

Returns: A unique_ptr to a value-initialized object of type + T[size].

+

Remarks: This overload shall only participate in overload + resolution when U is of the form T[].

-
template<typename U> // U is T[]
-unique_ptr<U> make_unique_noinit(size_t size);
-

Requires: The expression new T[size] shall be - well-formed.

-

Effects: Constructs an array of objects of type - U and size size via the expression - new T[size].

-
-

Examples

-

For objects with value-initialization.

-
-
unique_ptr<float> p1 = boost::make_unique<float>();
-unique_ptr<point> p2 = boost::make_unique<point>();
+

Examples:

+
+
unique_ptr<double[]> p1 = boost::make_unique<double[]>(4);
+unique_ptr<int[][2]> p2 = boost::make_unique<int[][2]>(2);
+
-

For objects with construction arguments.

+
template<typename U>
+unique_ptr<U> make_unique_noinit();
-
unique_ptr<float> p3 = boost::make_unique<float>(1.0f);
-unique_ptr<point> p4 = boost::make_unique<point>(x, y);
+

Returns: A unique_ptr to a default-initialized object of + type U.

+

Remarks: This overload shall only participate in overload + resolution when U is not an array type.

-

For objects with given value.

-
unique_ptr<string> p4 = boost::make_unique<string>({'a', 'b'});
-unique_ptr<type>   p5 = boost::make_unique<type>({3, 5, 4});
+

Examples:

+
+
unique_ptr<float> p1 = boost::make_unique_noinit<float>();
+unique_ptr<point> p2 = boost::make_unique_noinit<point>();
+
-

For objects with default-initialization.

+
template<typename U>
+unique_ptr<U> make_unique_noinit(size_t size);
-
unique_ptr<float> p6 = boost::make_unique_noinit<float>();
-unique_ptr<point> p7 = boost::make_unique_noinit<point>();
+

Returns: A unique_ptr to a default-initialized object of + type T[size].

+

Remarks: This overload shall only participate in overload + resolution when U is of the form T[].

-

For arrays with value-initialization.

-
unique_ptr<double[]> a1 = boost::make_unique<double[]>();
-unique_ptr<int[][4]> a2 = boost::make_unique<int[][4]>();
+

Examples:

+
+
unique_ptr<double[]> p1 = boost::make_unique_noinit<double[]>(4);
+unique_ptr<int[][2]> p2 = boost::make_unique_noinit<int[][2]>(2);
+
-

For arrays with default-initialization.

-
-
unique_ptr<double[]> a3 = boost::make_unique_noinit<double[]>();
-unique_ptr<int[][4]> a4 = boost::make_unique_noinit<int[][4]>();
-

History

January 2014. Glen Fernandes contributed implementations of make_unique for objects and arrays.

From 154a274916b1cbddd2eb92d4645f04dfb4ad2536 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Tue, 4 Feb 2014 00:29:51 -0800 Subject: [PATCH 22/39] Update make_shared for arrays to address 2070 This updates make_shared and allocate_shared for arrays in accordance with report 2070 which requires that allocator_traits::construct(a2, ptr, ...) is used for construction and allocator_traits::destroy(a2, ptr) is used for destruction instead of placement new and destructor invocation. --- .../boost/smart_ptr/allocate_shared_array.hpp | 38 +-- .../detail/allocate_array_helper.hpp | 118 ------- .../smart_ptr/detail/array_allocator.hpp | 272 +++++++++++++++ .../boost/smart_ptr/detail/array_deleter.hpp | 309 ++++++++++++++++-- .../smart_ptr/detail/array_size_base.hpp | 37 --- .../boost/smart_ptr/detail/array_utility.hpp | 131 -------- .../smart_ptr/detail/make_array_helper.hpp | 110 ------- include/boost/smart_ptr/make_shared_array.hpp | 39 ++- make_shared_array.html | 47 +-- make_unique.html | 12 - 10 files changed, 615 insertions(+), 498 deletions(-) delete mode 100644 include/boost/smart_ptr/detail/allocate_array_helper.hpp create mode 100644 include/boost/smart_ptr/detail/array_allocator.hpp delete mode 100644 include/boost/smart_ptr/detail/array_size_base.hpp delete mode 100644 include/boost/smart_ptr/detail/array_utility.hpp delete mode 100644 include/boost/smart_ptr/detail/make_array_helper.hpp diff --git a/include/boost/smart_ptr/allocate_shared_array.hpp b/include/boost/smart_ptr/allocate_shared_array.hpp index bac8cef..c35a106 100644 --- a/include/boost/smart_ptr/allocate_shared_array.hpp +++ b/include/boost/smart_ptr/allocate_shared_array.hpp @@ -9,7 +9,7 @@ #ifndef BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP #define BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP -#include +#include #include #include #include @@ -24,10 +24,10 @@ namespace boost { T1* p1 = 0; T3* p2 = 0; std::size_t n1 = size * boost::detail::array_total::size; - boost::detail::allocate_array_helper a1(allocator, n1, &p2); - boost::detail::array_deleter d1(n1); + boost::detail::as_allocator a1(allocator, n1, &p2); + boost::detail::as_deleter d1(allocator, n1); boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; + typedef boost::detail::as_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); d2->init(p2); @@ -45,10 +45,10 @@ namespace boost { }; T1* p1 = 0; T3* p2 = 0; - boost::detail::allocate_array_helper a1(allocator, &p2); - boost::detail::array_deleter d1; + boost::detail::as_allocator a1(allocator, &p2); + boost::detail::as_deleter d1(allocator); boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; + typedef boost::detail::as_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); d2->init(p2); @@ -70,10 +70,10 @@ namespace boost { T3* p2 = 0; T4* p3 = reinterpret_cast(&value); std::size_t n1 = M * size; - boost::detail::allocate_array_helper a1(allocator, n1, &p2); - boost::detail::array_deleter d1(n1); + boost::detail::as_allocator a1(allocator, n1, &p2); + boost::detail::as_deleter d1(allocator, n1); boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; + typedef boost::detail::as_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); d2->template init(p2, p3); @@ -95,10 +95,10 @@ namespace boost { T1* p1 = 0; T3* p2 = 0; T4* p3 = reinterpret_cast(&value); - boost::detail::allocate_array_helper a1(allocator, &p2); - boost::detail::array_deleter d1; + boost::detail::as_allocator a1(allocator, &p2); + boost::detail::as_deleter d1(allocator); boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; + typedef boost::detail::as_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); d2->template init(p2, p3); @@ -114,10 +114,10 @@ namespace boost { T1* p1 = 0; T3* p2 = 0; std::size_t n1 = size * boost::detail::array_total::size; - boost::detail::allocate_array_helper a1(allocator, n1, &p2); - boost::detail::array_deleter d1(n1); + boost::detail::as_allocator a1(allocator, n1, &p2); + boost::detail::ms_deleter d1(n1); boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; + typedef boost::detail::ms_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); d2->noinit(p2); @@ -135,10 +135,10 @@ namespace boost { }; T1* p1 = 0; T3* p2 = 0; - boost::detail::allocate_array_helper a1(allocator, &p2); - boost::detail::array_deleter d1; + boost::detail::as_allocator a1(allocator, &p2); + boost::detail::ms_deleter d1; boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; + typedef boost::detail::ms_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); d2->noinit(p2); diff --git a/include/boost/smart_ptr/detail/allocate_array_helper.hpp b/include/boost/smart_ptr/detail/allocate_array_helper.hpp deleted file mode 100644 index de43c76..0000000 --- a/include/boost/smart_ptr/detail/allocate_array_helper.hpp +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2012-2014 Glen Joseph Fernandes - * glenfe at live dot com - * - * Distributed under the Boost Software License, - * Version 1.0. (See accompanying file LICENSE_1_0.txt - * or copy at http://boost.org/LICENSE_1_0.txt) - */ -#ifndef BOOST_SMART_PTR_DETAIL_ALLOCATE_ARRAY_HELPER_HPP -#define BOOST_SMART_PTR_DETAIL_ALLOCATE_ARRAY_HELPER_HPP - -#include -#include -#include - -namespace boost { - namespace detail { - template - class allocate_array_helper - : array_size_base { - using array_size_base::size; - - template - friend class allocate_array_helper; - - typedef typename A::template rebind ::other A2; - typedef typename A::template rebind::other A3; - - public: - typedef typename array_inner::type type; - typedef typename A2::value_type value_type; - typedef typename A2::pointer pointer; - typedef typename A2::const_pointer const_pointer; - typedef typename A2::reference reference; - typedef typename A2::const_reference const_reference; - typedef typename A2::size_type size_type; - typedef typename A2::difference_type difference_type; - - template - struct rebind { - typedef allocate_array_helper other; - }; - - allocate_array_helper(const A& allocator_, type** data_) - : allocator(allocator_), - data(data_) { - } - - allocate_array_helper(const A& allocator_, std::size_t size_, type** data_) - : array_size_base(size_), - allocator(allocator_), - data(data_) { - } - - template - allocate_array_helper(const allocate_array_helper& other) - : array_size_base(other), - allocator(other.allocator), - data(other.data) { - } - - pointer address(reference value) const { - return allocator.address(value); - } - - const_pointer address(const_reference value) const { - return allocator.address(value); - } - - size_type max_size() const { - return allocator.max_size(); - } - - pointer allocate(size_type count, const void* value = 0) { - std::size_t a1 = boost::alignment_of::value; - std::size_t n1 = count * sizeof(Y) + a1 - 1; - char* p1 = A3(allocator).allocate(size + n1, value); - char* p2 = p1 + n1; - while (std::size_t(p2) % a1 != 0) { - p2--; - } - *data = reinterpret_cast(p2); - return reinterpret_cast(p1); - } - - void deallocate(pointer memory, size_type count) { - std::size_t a1 = boost::alignment_of::value; - std::size_t n1 = count * sizeof(Y) + a1 - 1; - char* p1 = reinterpret_cast(memory); - A3(allocator).deallocate(p1, size + n1); - } - - void construct(pointer memory, const Y& value) { - allocator.construct(memory, value); - } - - void destroy(pointer memory) { - allocator.destroy(memory); - } - - template - bool operator==(const allocate_array_helper& other) const { - return allocator == other.allocator; - } - - template - bool operator!=(const allocate_array_helper& other) const { - return !(*this == other); - } - - private: - A2 allocator; - type** data; - }; - } -} - -#endif diff --git a/include/boost/smart_ptr/detail/array_allocator.hpp b/include/boost/smart_ptr/detail/array_allocator.hpp new file mode 100644 index 0000000..3371545 --- /dev/null +++ b/include/boost/smart_ptr/detail/array_allocator.hpp @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2012-2014 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#ifndef BOOST_SMART_PTR_DETAIL_ARRAY_ALLOCATOR_HPP +#define BOOST_SMART_PTR_DETAIL_ARRAY_ALLOCATOR_HPP + +#include +#include +#if !defined(BOOST_NO_CXX11_ALLOCATOR) +#include +#endif + +namespace boost { + namespace detail { + template + struct ms_allocator_base; + + template + struct ms_allocator_base { + ms_allocator_base(std::size_t size_) + : size(size_ * sizeof(T)) { + } + + std::size_t size; + }; + + template + struct ms_allocator_base { + enum { + size = N * sizeof(T) + }; + }; + + template + class as_allocator + : ms_allocator_base { + using ms_allocator_base::size; + + template + friend class as_allocator; + +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + typedef typename std::allocator_traits:: + template rebind_alloc::other YA; + + typedef typename std::allocator_traits:: + template rebind_alloc::other CA; + + typedef typename std::allocator_traits:: + template rebind_traits::other YT; + + typedef typename std::allocator_traits:: + template rebind_traits::other CT; +#else + typedef typename A::template rebind::other YA; + typedef typename A::template rebind::other CA; +#endif + + public: + typedef typename array_inner::type type; + +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + typedef typename YT::value_type value_type; + typedef typename YT::pointer pointer; + typedef typename YT::const_pointer const_pointer; + typedef typename YT::size_type size_type; + typedef typename YT::difference_type difference_type; + typedef Y& reference; + typedef const Y& const_reference; +#else + typedef typename YA::value_type value_type; + typedef typename YA::pointer pointer; + typedef typename YA::const_pointer const_pointer; + typedef typename YA::size_type size_type; + typedef typename YA::difference_type difference_type; + typedef typename YA::reference reference; + typedef typename YA::const_reference const_reference; +#endif + + template + struct rebind { + typedef as_allocator other; + }; + + as_allocator(const A& allocator_, type** data_) + : allocator(allocator_), + data(data_) { + } + + as_allocator(const A& allocator_, std::size_t size_, type** data_) + : ms_allocator_base(size_), + allocator(allocator_), + data(data_) { + } + + template + as_allocator(const as_allocator& other) + : ms_allocator_base(other), + allocator(other.allocator), + data(other.data) { + } + + pointer address(reference value) const { + return allocator.address(value); + } + + const_pointer address(const_reference value) const { + return allocator.address(value); + } + + size_type max_size() const { + return allocator.max_size(); + } + + pointer allocate(size_type count, const void* value = 0) { + std::size_t a1 = boost::alignment_of::value; + std::size_t n1 = count * sizeof(Y) + a1 - 1; + CA ca(allocator); +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + char* p1 = CT::allocate(ca, size + n1, value); +#else + char* p1 = ca.allocate(size + n1, value); +#endif + char* p2 = p1 + n1; + while (std::size_t(p2) % a1 != 0) { + p2--; + } + *data = reinterpret_cast(p2); + return reinterpret_cast(p1); + } + + void deallocate(pointer memory, size_type count) { + std::size_t a1 = boost::alignment_of::value; + std::size_t n1 = count * sizeof(Y) + a1 - 1; + char* p1 = reinterpret_cast(memory); + CA ca(allocator); +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + CT::deallocate(ca, p1, size + n1); +#else + ca.deallocate(p1, size + n1); +#endif + } + + void construct(pointer memory, const Y& value) { +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + YT::construct(allocator, memory, value); +#else + allocator.construct(memory, value); +#endif + } + + void destroy(pointer memory) { +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + YT::destroy(allocator, memory); +#else + allocator.destroy(memory); +#endif + } + + template + bool operator==(const as_allocator& other) const { + return allocator == other.allocator; + } + + template + bool operator!=(const as_allocator& other) const { + return !(*this == other); + } + + private: + YA allocator; + type** data; + }; + + template + class ms_allocator + : ms_allocator_base { + using ms_allocator_base::size; + + template + friend class ms_allocator; + + public: + typedef typename array_inner::type type; + typedef Y value_type; + typedef Y* pointer; + typedef const Y* const_pointer; + typedef std::size_t size_type; + typedef ptrdiff_t difference_type; + typedef Y& reference; + typedef const Y& const_reference; + + template + struct rebind { + typedef ms_allocator other; + }; + + ms_allocator(type** data_) + : data(data_) { + } + + ms_allocator(std::size_t size_, type** data_) + : ms_allocator_base(size_), + data(data_) { + } + + template + ms_allocator(const ms_allocator& other) + : ms_allocator_base(other), + data(other.data) { + } + + pointer address(reference value) const { + return &value; + } + + const_pointer address(const_reference value) const { + return &value; + } + + size_type max_size() const { + return static_cast(-1) / sizeof(Y); + } + + pointer allocate(size_type count, const void* = 0) { + std::size_t a1 = boost::alignment_of::value; + std::size_t n1 = count * sizeof(Y)+a1 - 1; + void* p1 = ::operator new(n1 + size); + char* p2 = static_cast(p1)+n1; + while (std::size_t(p2) % a1 != 0) { + p2--; + } + *data = reinterpret_cast(p2); + return reinterpret_cast(p1); + } + + void deallocate(pointer memory, size_type) { + void* p1 = memory; + ::operator delete(p1); + } + + void construct(pointer memory, const Y& value) { + void* p1 = memory; + ::new(p1) Y(value); + } + + void destroy(pointer memory) { + memory->~Y(); + } + + template + bool operator==(const ms_allocator&) const { + return true; + } + + template + bool operator!=(const ms_allocator& other) const { + return !(*this == other); + } + + private: + type** data; + }; + } +} + +#endif diff --git a/include/boost/smart_ptr/detail/array_deleter.hpp b/include/boost/smart_ptr/detail/array_deleter.hpp index 58adbbc..7d99795 100644 --- a/include/boost/smart_ptr/detail/array_deleter.hpp +++ b/include/boost/smart_ptr/detail/array_deleter.hpp @@ -9,17 +9,22 @@ #ifndef BOOST_SMART_PTR_DETAIL_ARRAY_DELETER_HPP #define BOOST_SMART_PTR_DETAIL_ARRAY_DELETER_HPP +#include #include -#include +#include +#include +#if !defined(BOOST_NO_CXX11_ALLOCATOR) +#include +#endif namespace boost { namespace detail { template - struct array_count_base; + struct ms_deleter_base; template - struct array_count_base { - array_count_base(std::size_t size_) + struct ms_deleter_base { + ms_deleter_base(std::size_t size_) : size(size_) { } @@ -27,61 +32,305 @@ namespace boost { }; template - struct array_count_base { + struct ms_deleter_base { enum { size = N }; }; - template - class array_deleter - : array_count_base { - using array_count_base::size; + template + class as_deleter + : ms_deleter_base { + using ms_deleter_base::size; public: typedef typename array_inner::type type; - - array_deleter() - : object(0) { - } - array_deleter(std::size_t size_) - : array_count_base(size_), +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + as_deleter(const A& allocator_) + : allocator(allocator_), object(0) { } - - ~array_deleter() { - if (object) { - array_destroy(object, size); - } +#else + as_deleter(const A&) + : object(0) { } +#endif + +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + as_deleter(const A& allocator_, std::size_t size_) + : ms_deleter_base(size_), + allocator(allocator_), + object(0) { + } +#else + as_deleter(const A&, std::size_t size_) + : ms_deleter_base(size_), + object(0) { + } +#endif void init(type* memory) { - array_init(memory, size); + value_init(memory); object = memory; } template void init(type* memory, const type* value) { - array_init(memory, size, value); - object = memory; - } - - void noinit(type* memory) { - array_noinit(memory, size); + value_init(memory, value); object = memory; } void operator()(const void*) { if (object) { - array_destroy(object, size); - object = 0; + destroy(object, size); } } private: +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + typedef typename std::allocator_traits:: + template rebind_alloc::other TA; + + typedef typename std::allocator_traits:: + template rebind_traits::other TT; +#endif + + void destroy(type*, std::size_t, boost::true_type) { + } + + void destroy(type* memory, std::size_t n, boost::false_type) { + for (std::size_t i = n; i > 0;) { +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + TT::destroy(allocator, &memory[--i]); +#else + memory[--i].~type(); +#endif + } + } + + void destroy(type* memory, std::size_t n) { + boost::has_trivial_destructor tag; + destroy(memory, n, tag); + } + + void value_init(type* memory, boost::true_type) { + for (std::size_t i = 0; i < size; i++) { +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + TT::construct(allocator, memory + i); +#else + void* p1 = memory + i; + ::new(p1) type(); +#endif + } + } + + void value_init(type* memory, boost::false_type) { +#if !defined(BOOST_NO_EXCEPTIONS) + std::size_t i = 0; + try { + for (; i < size; i++) { +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + TT::construct(allocator, memory + i); +#else + void* p1 = memory + i; + ::new(p1) type(); +#endif + } + } catch (...) { + destroy(memory, i); + throw; + } +#else + for (std::size_t i = 0; i < size; i++) { +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + TT::construct(allocator, memory + i); +#else + void* p1 = memory + i; + ::new(p1) type(); +#endif + } +#endif + } + + void value_init(type* memory) { + boost::has_trivial_default_constructor tag; + value_init(memory, tag); + } + + template + void value_init(type* memory, const type* list) { +#if !defined(BOOST_NO_EXCEPTIONS) + std::size_t i = 0; + try { + for (; i < size; i++) { +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + TT::construct(allocator, memory + i, list[i % N]); +#else + void* p1 = memory + i; + ::new(p1) type(list[i % N]); +#endif + } + } catch (...) { + destroy(memory, i); + throw; + } +#else + for (std::size_t i = 0; i < size; i++) { +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + TT::construct(allocator, memory + i, list[i % N]); +#else + void* p1 = memory + i; + ::new(p1) type(list[i % N]); +#endif + } +#endif + } + +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + TA allocator; +#endif type* object; - }; + }; + + template + class ms_deleter + : ms_deleter_base { + using ms_deleter_base::size; + + public: + typedef typename array_inner::type type; + + ms_deleter() + : object(0) { + } + + ms_deleter(std::size_t size_) + : ms_deleter_base(size_), + object(0) { + } + + void init(type* memory) { + value_init(memory); + object = memory; + } + + template + void init(type* memory, const type* value) { + value_init(memory, value); + object = memory; + } + + void noinit(type* memory) { + default_init(memory); + object = memory; + } + + void operator()(const void*) { + if (object) { + destroy(object, size); + } + } + + private: + void destroy(type*, std::size_t, boost::true_type) { + } + + void destroy(type* memory, std::size_t n, boost::false_type) { + for (std::size_t i = n; i > 0;) { + memory[--i].~type(); + } + } + + void destroy(type* memory, std::size_t n) { + boost::has_trivial_destructor tag; + destroy(memory, n, tag); + } + + void value_init(type* memory, boost::true_type) { + for (std::size_t i = 0; i < size; i++) { + void* p1 = memory + i; + ::new(p1) type(); + } + } + + void value_init(type* memory, boost::false_type) { +#if !defined(BOOST_NO_EXCEPTIONS) + std::size_t i = 0; + try { + for (; i < size; i++) { + void* p1 = memory + i; + ::new(p1) type(); + } + } catch (...) { + destroy(memory, i); + throw; + } +#else + for (std::size_t i = 0; i < size; i++) { + void* p1 = memory + i; + ::new(p1) type(); + } +#endif + } + + void value_init(type* memory) { + boost::has_trivial_default_constructor tag; + value_init(memory, tag); + } + + void default_init(type*, boost::true_type) { + } + + void default_init(type* memory, boost::false_type) { +#if !defined(BOOST_NO_EXCEPTIONS) + std::size_t i = 0; + try { + for (; i < size; i++) { + void* p1 = memory + i; + ::new(p1) type; + } + } catch (...) { + destroy(memory, i); + throw; + } +#else + for (std::size_t i = 0; i < size; i++) { + void* p1 = memory + i; + ::new(p1) type; + } +#endif + } + + void default_init(type* memory) { + boost::has_trivial_default_constructor tag; + default_init(memory, tag); + } + + template + void value_init(type* memory, const type* list) { +#if !defined(BOOST_NO_EXCEPTIONS) + std::size_t i = 0; + try { + for (; i < size; i++) { + void* p1 = memory + i; + ::new(p1) type(list[i % N]); + } + } catch (...) { + destroy(memory, i); + throw; + } +#else + for (std::size_t i = 0; i < size; i++) { + void* p1 = memory + i; + ::new(p1) type(list[i % N]); + } +#endif + } + + private: + type* object; + }; } } diff --git a/include/boost/smart_ptr/detail/array_size_base.hpp b/include/boost/smart_ptr/detail/array_size_base.hpp deleted file mode 100644 index df5aab2..0000000 --- a/include/boost/smart_ptr/detail/array_size_base.hpp +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2014 Glen Joseph Fernandes - * glenfe at live dot com - * - * Distributed under the Boost Software License, - * Version 1.0. (See accompanying file LICENSE_1_0.txt - * or copy at http://boost.org/LICENSE_1_0.txt) - */ -#ifndef BOOST_SMART_PTR_DETAIL_ARRAY_SIZE_BASE_HPP -#define BOOST_SMART_PTR_DETAIL_ARRAY_SIZE_BASE_HPP - -#include - -namespace boost { - namespace detail { - template - struct array_size_base; - - template - struct array_size_base { - array_size_base(std::size_t size_) - : size(size_ * sizeof(T)) { - } - - std::size_t size; - }; - - template - struct array_size_base { - enum { - size = N * sizeof(T) - }; - }; - } -} - -#endif diff --git a/include/boost/smart_ptr/detail/array_utility.hpp b/include/boost/smart_ptr/detail/array_utility.hpp deleted file mode 100644 index d8444b8..0000000 --- a/include/boost/smart_ptr/detail/array_utility.hpp +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (c) 2012-2014 Glen Joseph Fernandes - * glenfe at live dot com - * - * Distributed under the Boost Software License, - * Version 1.0. (See accompanying file LICENSE_1_0.txt - * or copy at http://boost.org/LICENSE_1_0.txt) - */ -#ifndef BOOST_SMART_PTR_DETAIL_ARRAY_UTILITY_HPP -#define BOOST_SMART_PTR_DETAIL_ARRAY_UTILITY_HPP - -#include -#include -#include - -namespace boost { - namespace detail { - template - inline void array_destroy(T*, std::size_t, - boost::true_type) { - } - - template - inline void array_destroy(T* memory, std::size_t size, - boost::false_type) { - for (std::size_t i = size; i > 0; ) { - memory[--i].~T(); - } - } - - template - inline void array_destroy(T* memory, std::size_t size) { - boost::has_trivial_destructor type; - array_destroy(memory, size, type); - } - - template - inline void array_value(T* memory, std::size_t size, - boost::true_type) { - for (std::size_t i = 0; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T(); - } - } - - template - inline void array_value(T* memory, std::size_t size, - boost::false_type) { -#if !defined(BOOST_NO_EXCEPTIONS) - std::size_t i = 0; - try { - for (; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T(); - } - } catch (...) { - array_destroy(memory, i); - throw; - } -#else - for (std::size_t i = 0; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T(); - } -#endif - } - - template - inline void array_init(T* memory, std::size_t size) { - boost::has_trivial_default_constructor type; - array_value(memory, size, type); - } - - template - inline void array_init(T* memory, std::size_t size, - const T* list) { -#if !defined(BOOST_NO_EXCEPTIONS) - std::size_t i = 0; - try { - for (; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T(list[i % N]); - } - } catch (...) { - array_destroy(memory, i); - throw; - } -#else - for (std::size_t i = 0; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T(list[i % N]); - } -#endif - } - - template - inline void array_default(T*, std::size_t, - boost::true_type) { - } - - template - inline void array_default(T* memory, std::size_t size, - boost::false_type) { -#if !defined(BOOST_NO_EXCEPTIONS) - std::size_t i = 0; - try { - for (; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T; - } - } catch (...) { - array_destroy(memory, i); - throw; - } -#else - for (std::size_t i = 0; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T; - } -#endif - } - - template - inline void array_noinit(T* memory, std::size_t size) { - boost::has_trivial_default_constructor type; - array_default(memory, size, type); - } - } -} - -#endif diff --git a/include/boost/smart_ptr/detail/make_array_helper.hpp b/include/boost/smart_ptr/detail/make_array_helper.hpp deleted file mode 100644 index 3aebb6d..0000000 --- a/include/boost/smart_ptr/detail/make_array_helper.hpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2012-2104 Glen Joseph Fernandes - * glenfe at live dot com - * - * Distributed under the Boost Software License, - * Version 1.0. (See accompanying file LICENSE_1_0.txt - * or copy at http://boost.org/LICENSE_1_0.txt) - */ -#ifndef BOOST_SMART_PTR_DETAIL_MAKE_ARRAY_HELPER_HPP -#define BOOST_SMART_PTR_DETAIL_MAKE_ARRAY_HELPER_HPP - -#include -#include -#include - -namespace boost { - namespace detail { - template - class make_array_helper - : array_size_base { - using array_size_base::size; - - template - friend class make_array_helper; - - public: - typedef typename array_inner::type type; - typedef Y value_type; - typedef Y* pointer; - typedef const Y* const_pointer; - typedef Y& reference; - typedef const Y& const_reference; - typedef std::size_t size_type; - typedef ptrdiff_t difference_type; - - template - struct rebind { - typedef make_array_helper other; - }; - - make_array_helper(type** data_) - : data(data_) { - } - - make_array_helper(std::size_t size_, type** data_) - : array_size_base(size_), - data(data_) { - } - - template - make_array_helper(const make_array_helper& other) - : array_size_base(other), - data(other.data) { - } - - pointer address(reference value) const { - return &value; - } - - const_pointer address(const_reference value) const { - return &value; - } - - size_type max_size() const { - return static_cast(-1) / sizeof(Y); - } - - pointer allocate(size_type count, const void* = 0) { - std::size_t a1 = boost::alignment_of::value; - std::size_t n1 = count * sizeof(Y) + a1 - 1; - void* p1 = ::operator new(n1 + size); - char* p2 = static_cast(p1) + n1; - while (std::size_t(p2) % a1 != 0) { - p2--; - } - *data = reinterpret_cast(p2); - return reinterpret_cast(p1); - } - - void deallocate(pointer memory, size_type) { - void* p1 = memory; - ::operator delete(p1); - } - - void construct(pointer memory, const Y& value) { - void* p1 = memory; - ::new(p1) Y(value); - } - - void destroy(pointer memory) { - memory->~Y(); - } - - template - bool operator==(const make_array_helper&) const { - return true; - } - - template - bool operator!=(const make_array_helper& other) const { - return !(*this == other); - } - - private: - type** data; - }; - } -} - -#endif diff --git a/include/boost/smart_ptr/make_shared_array.hpp b/include/boost/smart_ptr/make_shared_array.hpp index 6a0bcfd..2deba39 100644 --- a/include/boost/smart_ptr/make_shared_array.hpp +++ b/include/boost/smart_ptr/make_shared_array.hpp @@ -9,9 +9,8 @@ #ifndef BOOST_SMART_PTR_MAKE_SHARED_ARRAY_HPP #define BOOST_SMART_PTR_MAKE_SHARED_ARRAY_HPP +#include #include -#include -#include #include #include @@ -25,10 +24,10 @@ namespace boost { T1* p1 = 0; T3* p2 = 0; std::size_t n1 = size * boost::detail::array_total::size; - boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1(n1); + boost::detail::ms_allocator a1(n1, &p2); + boost::detail::ms_deleter d1(n1); boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; + typedef boost::detail::ms_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); d2->init(p2); @@ -46,10 +45,10 @@ namespace boost { }; T1* p1 = 0; T3* p2 = 0; - boost::detail::make_array_helper a1(&p2); - boost::detail::array_deleter d1; + boost::detail::ms_allocator a1(&p2); + boost::detail::ms_deleter d1; boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; + typedef boost::detail::ms_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); d2->init(p2); @@ -71,10 +70,10 @@ namespace boost { T3* p2 = 0; T4* p3 = reinterpret_cast(&value); std::size_t n1 = M * size; - boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1(n1); + boost::detail::ms_allocator a1(n1, &p2); + boost::detail::ms_deleter d1(n1); boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; + typedef boost::detail::ms_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); d2->template init(p2, p3); @@ -95,10 +94,10 @@ namespace boost { T1* p1 = 0; T3* p2 = 0; T4* p3 = reinterpret_cast(&value); - boost::detail::make_array_helper a1(&p2); - boost::detail::array_deleter d1; + boost::detail::ms_allocator a1(&p2); + boost::detail::ms_deleter d1; boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; + typedef boost::detail::ms_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); d2->template init(p2, p3); @@ -114,10 +113,10 @@ namespace boost { T1* p1 = 0; T3* p2 = 0; std::size_t n1 = size * boost::detail::array_total::size; - boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1(n1); + boost::detail::ms_allocator a1(n1, &p2); + boost::detail::ms_deleter d1(n1); boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; + typedef boost::detail::ms_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); d2->noinit(p2); @@ -135,10 +134,10 @@ namespace boost { }; T1* p1 = 0; T3* p2 = 0; - boost::detail::make_array_helper a1(&p2); - boost::detail::array_deleter d1; + boost::detail::ms_allocator a1(&p2); + boost::detail::ms_deleter d1; boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::array_deleter* D2; + typedef boost::detail::ms_deleter* D2; p1 = reinterpret_cast(p2); D2 d2 = static_cast(s1._internal_get_untyped_deleter()); d2->noinit(p2); diff --git a/make_shared_array.html b/make_shared_array.html index 76e4f20..28a7a11 100644 --- a/make_shared_array.html +++ b/make_shared_array.html @@ -97,8 +97,6 @@ template<typename U, typename A>

Throws: bad_alloc, an exception thrown from A::allocate, or from the initialization of the object.

-
-

Remarks:

This implementation performs no more than one memory @@ -115,18 +113,34 @@ template<typename U, typename A>

Array elements are initialized in ascending order of their addresses.

When a subobject of a non-array type T is specified to - be initialized to a value value, or to - T(list...), where list... is a list of - constructor arguments, make_shared shall perform this - initialization via the expression ::new(ptr) T(value) - or ::new(ptr) T(list...) respectively, where - ptr has type void* and points to storage - suitable to hold an object of type T.

+ be initialized to a value value, + make_shared shall perform this initialization via the + expression ::new(ptr) T(value), where ptr + has type void* and points to storage suitable to hold + an object of type T.

+

When a subobject of non-array type T is specified to + be initialized to a value value, + allocate_shared shall perform this initialization via + the expression allocator_traits<A2>::construct(a2, ptr, + value), where ptr points to storage suitable to + hold an object of type T and a2 of type A2 + is a rebound copy of the allocator allocator passed to + allocate_shared such that its value_type + is T.

When a subobject of non-array type T is specified to be value-initialized, make_shared shall perform this initialization via the expression ::new(ptr) T(), where ptr has type void* and points to storage suitable to hold an object of type T.

+

When a subobject of non-array type T is specified to + be value-initialized, allocate_shared shall perform + this initialization via the expression + allocator_traits<A2>::construct(a2, ptr), where + ptr points to storage suitable to hold an object + of type T and a2 of type A2 is a rebound + copy of the allocator allocator passed to + allocate_shared such that its value_type + is T.

When a subobject of non-array type T is specified to be default-initialized, make_shared_noinit and allocate_shared_noinit shall perform this @@ -138,6 +152,9 @@ template<typename U, typename A> the initialized elements should be destroyed in the reverse order of their construction.

+

Notes: These functions will typically allocate more memory + than sizeof(U) to allow for internal bookkeeping + structures such as the reference counts.

Free Functions

template<typename U> 
@@ -149,8 +166,6 @@ template<typename U, typename A>
         object of type T[size].

Remarks: These overloads shall only participate in overload resolution when U is of the form T[].

- -

Examples:

boost::shared_ptr<int[]> a1 = boost::make_shared<int[]>(size);
@@ -166,8 +181,6 @@ template<typename U, typename A>
         object of type T[N].

Remarks: These overloads shall only participate in overload resolution when U is of the form T[N].

-
-

Examples:

boost::shared_ptr<int[8]> a1 = boost::make_shared<int[8]>();
@@ -184,8 +197,6 @@ template<typename U, typename A>
         is initialized to value.

Remarks: These overloads shall only participate in overload resolution when U is of the form T[].

-
-

Examples:

boost::shared_ptr<int[]> a1 = boost::make_shared<int[]>(size, 1);
@@ -202,8 +213,6 @@ template<typename U, typename A>
         initialized to value.

Remarks: These overloads shall only participate in overload resolution when U is of the form T[N].

-
-

Examples:

boost::shared_ptr<int[8]> a1 = boost::make_shared<int[8]>(1);
@@ -219,8 +228,6 @@ template<typename U, typename A>
         object of type T[size].

Remarks: These overloads shall only participate in overload resolution when U is of the form T[].

-
-

Examples:

boost::shared_ptr<int[]> a1 = boost::make_shared_noinit<int[]>(size);
@@ -236,8 +243,6 @@ template<typename U, typename A>
         object of type T[N].

Remarks: These overloads shall only participate in overload resolution when U is of the form T[N].

-
-

Examples:

boost::shared_ptr<int[8]> a1 = boost::make_shared_noinit<int[8]>();
diff --git a/make_unique.html b/make_unique.html
index fc46428..f1246db 100644
--- a/make_unique.html
+++ b/make_unique.html
@@ -56,8 +56,6 @@ template<typename U>
         r is the return value.

Throws: bad_alloc, or an exception thrown from the initialization of the object.

-
-

Remarks:

When an object of a non-array type T is specified to @@ -82,8 +80,6 @@ unique_ptr<U> make_unique(Args&&... args);

initialized to U(forward<Args>(args)...).

Remarks: This overload shall only participate in overload resolution when U is not an array type.

- -

Examples:

unique_ptr<float> p1 = boost::make_unique<float>();
@@ -97,8 +93,6 @@ unique_ptr<U> make_unique(U&& value);
initialized to move(value).

Remarks: This overload shall only participate in overload resolution when U is not an array type.

-
-

Examples:

unique_ptr<string> p1 = boost::make_unique<string>({'a', 'b'});
@@ -112,8 +106,6 @@ unique_ptr<U> make_unique(size_t size);
T[size].

Remarks: This overload shall only participate in overload resolution when U is of the form T[].

-
-

Examples:

unique_ptr<double[]> p1 = boost::make_unique<double[]>(4);
@@ -127,8 +119,6 @@ unique_ptr<U> make_unique_noinit();
type U.

Remarks: This overload shall only participate in overload resolution when U is not an array type.

-
-

Examples:

unique_ptr<float> p1 = boost::make_unique_noinit<float>();
@@ -142,8 +132,6 @@ unique_ptr<U> make_unique_noinit(size_t size);
type T[size].

Remarks: This overload shall only participate in overload resolution when U is of the form T[].

-
-

Examples:

unique_ptr<double[]> p1 = boost::make_unique_noinit<double[]>(4);

From e8595a05af337caea445be872f041c731bf2592e Mon Sep 17 00:00:00 2001
From: Glen Fernandes 
Date: Tue, 4 Feb 2014 08:43:36 -0800
Subject: [PATCH 23/39] Fix use of rebind_traits and rebind_alloc

---
 include/boost/smart_ptr/detail/array_allocator.hpp | 11 ++++-------
 include/boost/smart_ptr/detail/array_deleter.hpp   |  5 ++---
 2 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/include/boost/smart_ptr/detail/array_allocator.hpp b/include/boost/smart_ptr/detail/array_allocator.hpp
index 3371545..8b682eb 100644
--- a/include/boost/smart_ptr/detail/array_allocator.hpp
+++ b/include/boost/smart_ptr/detail/array_allocator.hpp
@@ -46,16 +46,13 @@ namespace boost {
 
 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
             typedef typename std::allocator_traits::
-                template rebind_alloc::other YA;
-
+                template rebind_alloc YA;
             typedef typename std::allocator_traits::
-                template rebind_alloc::other CA;
-
+                template rebind_alloc CA;
             typedef typename std::allocator_traits::
-                template rebind_traits::other YT;
-
+                template rebind_traits YT;
             typedef typename std::allocator_traits::
-                template rebind_traits::other CT;
+                template rebind_traits CT;
 #else
             typedef typename A::template rebind::other YA;
             typedef typename A::template rebind::other CA;
diff --git a/include/boost/smart_ptr/detail/array_deleter.hpp b/include/boost/smart_ptr/detail/array_deleter.hpp
index 7d99795..529c112 100644
--- a/include/boost/smart_ptr/detail/array_deleter.hpp
+++ b/include/boost/smart_ptr/detail/array_deleter.hpp
@@ -90,10 +90,9 @@ namespace boost {
         private:
 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
             typedef typename std::allocator_traits::
-                template rebind_alloc::other TA;
-
+                template rebind_alloc TA;
             typedef typename std::allocator_traits::
-                template rebind_traits::other TT;
+                template rebind_traits TT;
 #endif
 
             void destroy(type*, std::size_t, boost::true_type) {

From 51ab46a07dd90af4c3b0f6c8fd9e40a45c7fd9ea Mon Sep 17 00:00:00 2001
From: Glen Fernandes 
Date: Tue, 4 Feb 2014 08:43:36 -0800
Subject: [PATCH 24/39] Fix use of rebind_traits and rebind_alloc

---
 .../smart_ptr/detail/array_allocator.hpp      | 56 +++++++++----------
 .../boost/smart_ptr/detail/array_deleter.hpp  | 56 +++++++------------
 include/boost/smart_ptr/detail/as_pair.hpp    | 29 ++++++++++
 3 files changed, 76 insertions(+), 65 deletions(-)
 create mode 100644 include/boost/smart_ptr/detail/as_pair.hpp

diff --git a/include/boost/smart_ptr/detail/array_allocator.hpp b/include/boost/smart_ptr/detail/array_allocator.hpp
index 3371545..bac8984 100644
--- a/include/boost/smart_ptr/detail/array_allocator.hpp
+++ b/include/boost/smart_ptr/detail/array_allocator.hpp
@@ -10,6 +10,7 @@
 #define BOOST_SMART_PTR_DETAIL_ARRAY_ALLOCATOR_HPP
 
 #include 
+#include 
 #include 
 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
 #include 
@@ -46,19 +47,18 @@ namespace boost {
 
 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
             typedef typename std::allocator_traits::
-                template rebind_alloc::other YA;
-
+                template rebind_alloc YA;
             typedef typename std::allocator_traits::
-                template rebind_alloc::other CA;
-
+                template rebind_alloc CA;
             typedef typename std::allocator_traits::
-                template rebind_traits::other YT;
-
+                template rebind_traits YT;
             typedef typename std::allocator_traits::
-                template rebind_traits::other CT;
+                template rebind_traits CT;
 #else
-            typedef typename A::template rebind::other YA;
-            typedef typename A::template rebind::other CA;
+            typedef typename A::
+                template rebind::other YA;
+            typedef typename A::
+                template rebind::other CA;
 #endif
 
         public:
@@ -87,40 +87,37 @@ namespace boost {
                 typedef as_allocator other;
             };
 
-            as_allocator(const A& allocator_, type** data_)
-                : allocator(allocator_),
-                  data(data_) {
+            as_allocator(const A& allocator, type** data)
+                : pair(allocator, data) {
             }
 
-            as_allocator(const A& allocator_, std::size_t size_, type** data_)
+            as_allocator(const A& allocator, std::size_t size_, type** data)
                 : ms_allocator_base(size_),
-                  allocator(allocator_),
-                  data(data_) {
+                  pair(allocator, data) {
             }
 
             template
             as_allocator(const as_allocator& other) 
                 : ms_allocator_base(other),
-                  allocator(other.allocator),
-                  data(other.data) {
+                  pair(other.pair, other.pair.data) {
             }
 
             pointer address(reference value) const {
-                return allocator.address(value);
+                return pair.address(value);
             }
 
             const_pointer address(const_reference value) const {
-                return allocator.address(value);
+                return pair.address(value);
             }
 
             size_type max_size() const {
-                return allocator.max_size();
+                return pair.max_size();
             }
 
             pointer allocate(size_type count, const void* value = 0) {
                 std::size_t a1 = boost::alignment_of::value;
                 std::size_t n1 = count * sizeof(Y) + a1 - 1;
-                CA ca(allocator);
+                CA ca(pair);
 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
                 char* p1 = CT::allocate(ca, size + n1, value);
 #else
@@ -130,7 +127,7 @@ namespace boost {
                 while (std::size_t(p2) % a1 != 0) {
                     p2--;
                 }
-                *data = reinterpret_cast(p2);
+                *pair.data = reinterpret_cast(p2);
                 return reinterpret_cast(p1);
             }
 
@@ -138,7 +135,7 @@ namespace boost {
                 std::size_t a1 = boost::alignment_of::value;
                 std::size_t n1 = count * sizeof(Y) + a1 - 1;
                 char* p1 = reinterpret_cast(memory);
-                CA ca(allocator);
+                CA ca(pair);
 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
                 CT::deallocate(ca, p1, size + n1);
 #else
@@ -148,23 +145,23 @@ namespace boost {
 
             void construct(pointer memory, const Y& value) {
 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
-                YT::construct(allocator, memory, value);
+                YT::construct(pair, memory, value);
 #else
-                allocator.construct(memory, value);
+                pair.construct(memory, value);
 #endif
             }
 
             void destroy(pointer memory) {
 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
-                YT::destroy(allocator, memory);
+                YT::destroy(pair, memory);
 #else
-                allocator.destroy(memory);
+                pair.destroy(memory);
 #endif
             }
 
             template
             bool operator==(const as_allocator& other) const {
-                return allocator == other.allocator;
+                return pair == other.pair;
             }
 
             template
@@ -173,8 +170,7 @@ namespace boost {
             }
 
         private:
-            YA allocator;
-            type** data;
+            as_pair pair;
         };
 
         template
diff --git a/include/boost/smart_ptr/detail/array_deleter.hpp b/include/boost/smart_ptr/detail/array_deleter.hpp
index 7d99795..b4ed44f 100644
--- a/include/boost/smart_ptr/detail/array_deleter.hpp
+++ b/include/boost/smart_ptr/detail/array_deleter.hpp
@@ -11,6 +11,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
@@ -46,54 +47,42 @@ namespace boost {
         public:
             typedef typename array_inner::type type;
 
-#if !defined(BOOST_NO_CXX11_ALLOCATOR)
-            as_deleter(const A& allocator_) 
-                : allocator(allocator_),
-                  object(0) {
+            as_deleter(const A& allocator) 
+                : pair(allocator, 0) {
             }
-#else
-            as_deleter(const A&)
-                : object(0) {
-            }
-#endif
 
-#if !defined(BOOST_NO_CXX11_ALLOCATOR)
-            as_deleter(const A& allocator_, std::size_t size_)
+            as_deleter(const A& allocator, std::size_t size_)
                 : ms_deleter_base(size_),
-                  allocator(allocator_),
-                  object(0) {
+                  pair(allocator, 0) {
             }
-#else
-            as_deleter(const A&, std::size_t size_)
-                : ms_deleter_base(size_),
-                  object(0) {
-            }
-#endif
 
             void init(type* memory) {
                 value_init(memory);
-                object = memory;
+                pair.data = memory;
             }
 
             template
             void init(type* memory, const type* value) {
                 value_init(memory, value);
-                object = memory;
+                pair.data = memory;
             }
 
             void operator()(const void*) {
-                if (object) {
-                    destroy(object, size);
+                if (pair.data) {
+                    destroy(pair.data, size);
                 }
             }
 
         private:
+
 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
             typedef typename std::allocator_traits::
-                template rebind_alloc::other TA;
-
+                template rebind_alloc TA;
             typedef typename std::allocator_traits::
-                template rebind_traits::other TT;
+                template rebind_traits TT;
+#else
+            typedef typename A::
+                template rebind::other TA;
 #endif
 
             void destroy(type*, std::size_t, boost::true_type) {
@@ -102,7 +91,7 @@ namespace boost {
             void destroy(type* memory, std::size_t n, boost::false_type) {
                 for (std::size_t i = n; i > 0;) {
 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
-                    TT::destroy(allocator, &memory[--i]);
+                    TT::destroy(pair, &memory[--i]);
 #else
                     memory[--i].~type();
 #endif
@@ -117,7 +106,7 @@ namespace boost {
             void value_init(type* memory, boost::true_type) {
                 for (std::size_t i = 0; i < size; i++) {
 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
-                    TT::construct(allocator, memory + i);
+                    TT::construct(pair, memory + i);
 #else
                     void* p1 = memory + i;
                     ::new(p1) type();
@@ -131,7 +120,7 @@ namespace boost {
                 try {
                     for (; i < size; i++) {
 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
-                        TT::construct(allocator, memory + i);
+                        TT::construct(pair, memory + i);
 #else
                         void* p1 = memory + i;
                         ::new(p1) type();
@@ -144,7 +133,7 @@ namespace boost {
 #else
                 for (std::size_t i = 0; i < size; i++) {
 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
-                    TT::construct(allocator, memory + i);
+                    TT::construct(pair, memory + i);
 #else
                     void* p1 = memory + i;
                     ::new(p1) type();
@@ -165,7 +154,7 @@ namespace boost {
                 try {
                     for (; i < size; i++) {
 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
-                        TT::construct(allocator, memory + i, list[i % N]);
+                        TT::construct(pair, memory + i, list[i % N]);
 #else
                         void* p1 = memory + i;
                         ::new(p1) type(list[i % N]);
@@ -187,10 +176,7 @@ namespace boost {
 #endif
             }
 
-#if !defined(BOOST_NO_CXX11_ALLOCATOR)
-            TA allocator;
-#endif
-            type* object;
+            as_pair pair;
         };
 
         template
diff --git a/include/boost/smart_ptr/detail/as_pair.hpp b/include/boost/smart_ptr/detail/as_pair.hpp
new file mode 100644
index 0000000..829adc0
--- /dev/null
+++ b/include/boost/smart_ptr/detail/as_pair.hpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2014 Glen Joseph Fernandes 
+ * glenfe at live dot com
+ *
+ * Distributed under the Boost Software License, 
+ * Version 1.0. (See accompanying file LICENSE_1_0.txt 
+ * or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+#ifndef BOOST_SMART_PTR_DETAIL_AS_PAIR_HPP
+#define BOOST_SMART_PTR_DETAIL_AS_PAIR_HPP
+
+#include 
+
+namespace boost {
+    namespace detail {
+        template
+        struct as_pair
+            : A {
+            as_pair(const A& allocator, const T& value)
+                : A(allocator),
+                  data(value) {
+            }
+
+            T data;
+        };
+    }
+}
+
+#endif

From f27b780724e2af140dae213968ab1c5c9f8f310b Mon Sep 17 00:00:00 2001
From: Glen Fernandes 
Date: Tue, 4 Feb 2014 13:16:06 -0800
Subject: [PATCH 25/39] Add unit test for allocate_shared construct case

---
 test/Jamfile.v2                               |   1 +
 test/allocate_shared_array_construct_test.cpp | 160 ++++++++++++++++++
 2 files changed, 161 insertions(+)
 create mode 100644 test/allocate_shared_array_construct_test.cpp

diff --git a/test/Jamfile.v2 b/test/Jamfile.v2
index 09263d3..8a74194 100644
--- a/test/Jamfile.v2
+++ b/test/Jamfile.v2
@@ -148,6 +148,7 @@ import testing ;
           [ run allocate_shared_array_esft_test.cpp ]
           [ run allocate_shared_array_noinit_test.cpp ]
           [ run allocate_shared_array_value_test.cpp ]
+          [ run allocate_shared_array_construct_test.cpp ]
 
           [ run make_unique_test.cpp ]
           [ run make_unique_args_test.cpp ]
diff --git a/test/allocate_shared_array_construct_test.cpp b/test/allocate_shared_array_construct_test.cpp
new file mode 100644
index 0000000..623aa65
--- /dev/null
+++ b/test/allocate_shared_array_construct_test.cpp
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2012-2014 Glen Joseph Fernandes 
+ * glenfe at live dot com
+ *
+ * Distributed under the Boost Software License, 
+ * Version 1.0. (See accompanying file LICENSE_1_0.txt 
+ * or copy at http://boost.org/LICENSE_1_0.txt)
+ */
+#include 
+#if !defined(BOOST_NO_CXX11_ALLOCATOR)
+#include 
+
+template
+class creator {
+public:
+    typedef T value_type;
+
+    creator() {
+    }
+
+    template
+    creator(const creator&) {
+    }
+
+    T* allocate(std::size_t size) {
+        void* p1 = ::operator new(size * sizeof(T));
+        return static_cast(p1);
+    }
+
+    void deallocate(T* memory, std::size_t) {
+        void* p1 = memory;
+        ::operator delete(p1);
+    }
+
+    template
+    void construct(U* memory, Args&&... args) {
+        void* p1 = memory;
+        ::new(p1) U(std::forward(args)...);
+    }
+
+    template
+    void destroy(U* memory) {
+        memory->~U();
+    }
+};
+
+class type {
+    friend class creator;
+
+public:
+    static unsigned int instances;
+    static type object;
+
+protected:
+    explicit type() {
+        instances++;
+    }
+
+    type(const type&) {
+        instances++;
+    }
+
+    ~type() {
+        instances--;
+    }
+};
+
+unsigned int type::instances;
+type type::object;
+
+int main() {
+    BOOST_TEST(type::instances == 1);
+    {
+        boost::shared_ptr a1 = boost::allocate_shared(creator(), 3);
+        BOOST_TEST(a1.use_count() == 1);
+        BOOST_TEST(a1.get() != 0);
+        BOOST_TEST(type::instances == 4);
+        a1.reset();
+        BOOST_TEST(type::instances == 1);
+    }
+
+    BOOST_TEST(type::instances == 1);
+    {
+        boost::shared_ptr a1 = boost::allocate_shared(creator());
+        BOOST_TEST(a1.use_count() == 1);
+        BOOST_TEST(a1.get() != 0);
+        BOOST_TEST(type::instances == 4);
+        a1.reset();
+        BOOST_TEST(type::instances == 1);
+    }
+
+    BOOST_TEST(type::instances == 1);
+    {
+        boost::shared_ptr a1 = boost::allocate_shared(creator(), 2);
+        BOOST_TEST(a1.get() != 0);
+        BOOST_TEST(a1.use_count() == 1);
+        BOOST_TEST(type::instances == 5);
+        a1.reset();
+        BOOST_TEST(type::instances == 1);
+    }
+
+    BOOST_TEST(type::instances == 1);
+    {
+        boost::shared_ptr a1 = boost::allocate_shared(creator());
+        BOOST_TEST(a1.get() != 0);
+        BOOST_TEST(a1.use_count() == 1);
+        BOOST_TEST(type::instances == 5);
+        a1.reset();
+        BOOST_TEST(type::instances == 1);
+    }
+
+    BOOST_TEST(type::instances == 1);
+    {
+        boost::shared_ptr a1 = boost::allocate_shared(creator(), 3);
+        BOOST_TEST(a1.get() != 0);
+        BOOST_TEST(a1.use_count() == 1);
+        BOOST_TEST(type::instances == 4);
+        a1.reset();
+        BOOST_TEST(type::instances == 1);
+    }
+
+    BOOST_TEST(type::instances == 1);
+    {
+        boost::shared_ptr a1 = boost::allocate_shared(creator());
+        BOOST_TEST(a1.get() != 0);
+        BOOST_TEST(a1.use_count() == 1);
+        BOOST_TEST(type::instances == 4);
+        a1.reset();
+        BOOST_TEST(type::instances == 1);
+    }
+
+    BOOST_TEST(type::instances == 1);
+    {
+        boost::shared_ptr a1 = boost::allocate_shared(creator(), 2);
+        BOOST_TEST(a1.get() != 0);
+        BOOST_TEST(a1.use_count() == 1);
+        BOOST_TEST(type::instances == 5);
+        a1.reset();
+        BOOST_TEST(type::instances == 1);
+    }
+
+    BOOST_TEST(type::instances == 1);
+    {
+        boost::shared_ptr a1 = boost::allocate_shared(creator());
+        BOOST_TEST(a1.get() != 0);
+        BOOST_TEST(a1.use_count() == 1);
+        BOOST_TEST(type::instances == 5);
+        a1.reset();
+        BOOST_TEST(type::instances == 1);
+    }
+
+    return boost::report_errors();
+}
+#else
+
+int main() {
+    return 0;
+}
+
+#endif

From 90e74511f7c32d4c120790fcc4153dd34d2c6bbe Mon Sep 17 00:00:00 2001
From: Peter Dimov 
Date: Wed, 5 Feb 2014 00:17:34 +0200
Subject: [PATCH 26/39] Add support and tests for C++11 minimal allocators

---
 .../boost/smart_ptr/detail/shared_count.hpp   |  80 +++++-
 .../smart_ptr/detail/sp_counted_impl.hpp      |   8 +
 test/Jamfile.v2                               |   3 +
 test/allocate_shared_alloc11_test.cpp         | 241 ++++++++++++++++++
 test/shared_ptr_alloc11_test.cpp              | 116 +++++++++
 test/shared_ptr_alloc2_test.cpp               |   4 +-
 test/shared_ptr_alloc3_test.cpp               |  78 ++++++
 7 files changed, 524 insertions(+), 6 deletions(-)
 create mode 100644 test/allocate_shared_alloc11_test.cpp
 create mode 100644 test/shared_ptr_alloc11_test.cpp
 create mode 100644 test/shared_ptr_alloc3_test.cpp

diff --git a/include/boost/smart_ptr/detail/shared_count.hpp b/include/boost/smart_ptr/detail/shared_count.hpp
index 8e1dd48..1e7d688 100644
--- a/include/boost/smart_ptr/detail/shared_count.hpp
+++ b/include/boost/smart_ptr/detail/shared_count.hpp
@@ -225,16 +225,35 @@ public:
 #endif
     {
         typedef sp_counted_impl_pda impl_type;
+
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+        typedef typename std::allocator_traits::template rebind_alloc< impl_type > A2;
+
+#else
+
         typedef typename A::template rebind< impl_type >::other A2;
 
+#endif
+
         A2 a2( a );
 
 #ifndef BOOST_NO_EXCEPTIONS
 
         try
         {
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+            impl_type * pi = std::allocator_traits::allocate( a2, 1 );
+            pi_ = pi;
+            std::allocator_traits::construct( a2, pi, p, d, a );
+
+#else
+
             pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );
-            new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
+            ::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
+
+#endif
         }
         catch(...)
         {
@@ -248,13 +267,30 @@ public:
             throw;
         }
 
+#else
+
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+        impl_type * pi = std::allocator_traits::allocate( a2, 1 );
+        pi_ = pi;
+
 #else
 
         pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );
 
+#endif
+
         if( pi_ != 0 )
         {
-            new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+            std::allocator_traits::construct( a2, pi, p, d, a );
+
+#else
+
+            ::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
+
+#endif
         }
         else
         {
@@ -273,16 +309,35 @@ public:
 #endif
     {
         typedef sp_counted_impl_pda< P, D, A > impl_type;
+
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+        typedef typename std::allocator_traits::template rebind_alloc< impl_type > A2;
+
+#else
+
         typedef typename A::template rebind< impl_type >::other A2;
 
+#endif
+
         A2 a2( a );
 
 #ifndef BOOST_NO_EXCEPTIONS
 
         try
         {
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+            impl_type * pi = std::allocator_traits::allocate( a2, 1 );
+            pi_ = pi;
+            std::allocator_traits::construct( a2, pi, p, a );
+
+#else
+
             pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );
-            new( static_cast< void* >( pi_ ) ) impl_type( p, a );
+            ::new( static_cast< void* >( pi_ ) ) impl_type( p, a );
+
+#endif
         }
         catch(...)
         {
@@ -296,13 +351,30 @@ public:
             throw;
         }
 
+#else
+
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+        impl_type * pi = std::allocator_traits::allocate( a2, 1 );
+        pi_ = pi;
+
 #else
 
         pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );
 
+#endif
+
         if( pi_ != 0 )
         {
-            new( static_cast< void* >( pi_ ) ) impl_type( p, a );
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+            std::allocator_traits::construct( a2, pi, p, a );
+
+#else
+
+            ::new( static_cast< void* >( pi_ ) ) impl_type( p, a );
+
+#endif
         }
         else
         {
diff --git a/include/boost/smart_ptr/detail/sp_counted_impl.hpp b/include/boost/smart_ptr/detail/sp_counted_impl.hpp
index d15cd3c..404f982 100644
--- a/include/boost/smart_ptr/detail/sp_counted_impl.hpp
+++ b/include/boost/smart_ptr/detail/sp_counted_impl.hpp
@@ -224,8 +224,16 @@ public:
 
     virtual void destroy() // nothrow
     {
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+        typedef typename std::allocator_traits::template rebind_alloc< this_type > A2;
+
+#else
+
         typedef typename A::template rebind< this_type >::other A2;
 
+#endif
+
         A2 a2( a_ );
 
         this->~this_type();
diff --git a/test/Jamfile.v2 b/test/Jamfile.v2
index 09263d3..d43f696 100644
--- a/test/Jamfile.v2
+++ b/test/Jamfile.v2
@@ -79,6 +79,9 @@ import testing ;
           [ run sp_zero_compare_test.cpp ]
           [ run sp_nullptr_test.cpp ]
           [ run sa_nullptr_test.cpp ]
+          [ run shared_ptr_alloc3_test.cpp ]
+          [ run shared_ptr_alloc11_test.cpp ]
+          [ run allocate_shared_alloc11_test.cpp ]
 
           [ compile-fail array_fail_spa_sp_c.cpp ]
           [ compile-fail array_fail_sp_spa_c.cpp ]
diff --git a/test/allocate_shared_alloc11_test.cpp b/test/allocate_shared_alloc11_test.cpp
new file mode 100644
index 0000000..bf2a402
--- /dev/null
+++ b/test/allocate_shared_alloc11_test.cpp
@@ -0,0 +1,241 @@
+// allocate_shared_alloc11_test.cpp
+//
+// allocate_shared with a minimal C++11 allocator
+//
+// Copyright 2007-2009, 2014 Peter Dimov
+//
+// 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
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+template< class T > class cxx11_allocator
+{
+public:
+
+    typedef T value_type;
+
+    cxx11_allocator()
+    {
+    }
+
+    template< class Y > cxx11_allocator( cxx11_allocator const & )
+    {
+    }
+
+    T * allocate( std::size_t n )
+    {
+        return static_cast< T* >( ::operator new( n * sizeof( T ) ) );
+    }
+
+    void deallocate( T * p, std::size_t n )
+    {
+        ::operator delete( p );
+    }
+};
+
+class X
+{
+private:
+
+    X( X const & );
+    X & operator=( X const & );
+
+    void * operator new( std::size_t n )
+    {
+        BOOST_ERROR( "private X::new called" );
+        return ::operator new( n );
+    }
+
+    void operator delete( void * p )
+    {
+        BOOST_ERROR( "private X::delete called" );
+        ::operator delete( p );
+    }
+
+public:
+
+    static int instances;
+
+    int v;
+
+    explicit X( int a1 = 0, int a2 = 0, int a3 = 0, int a4 = 0, int a5 = 0, int a6 = 0, int a7 = 0, int a8 = 0, int a9 = 0 ): v( a1+a2+a3+a4+a5+a6+a7+a8+a9 )
+    {
+        ++instances;
+    }
+
+    ~X()
+    {
+        --instances;
+    }
+};
+
+int X::instances = 0;
+
+int main()
+{
+    {
+        boost::shared_ptr< int > pi = boost::allocate_shared< int >( cxx11_allocator() );
+
+        BOOST_TEST( pi.get() != 0 );
+        BOOST_TEST( *pi == 0 );
+    }
+
+    {
+        boost::shared_ptr< int > pi = boost::allocate_shared< int >( cxx11_allocator(), 5 );
+
+        BOOST_TEST( pi.get() != 0 );
+        BOOST_TEST( *pi == 5 );
+    }
+
+    BOOST_TEST( X::instances == 0 );
+
+    {
+        boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator() );
+        boost::weak_ptr wp( pi );
+
+        BOOST_TEST( X::instances == 1 );
+        BOOST_TEST( pi.get() != 0 );
+        BOOST_TEST( pi->v == 0 );
+
+        pi.reset();
+
+        BOOST_TEST( X::instances == 0 );
+    }
+
+    {
+        boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator(), 1 );
+        boost::weak_ptr wp( pi );
+
+        BOOST_TEST( X::instances == 1 );
+        BOOST_TEST( pi.get() != 0 );
+        BOOST_TEST( pi->v == 1 );
+
+        pi.reset();
+
+        BOOST_TEST( X::instances == 0 );
+    }
+
+    {
+        boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator(), 1, 2 );
+        boost::weak_ptr wp( pi );
+
+        BOOST_TEST( X::instances == 1 );
+        BOOST_TEST( pi.get() != 0 );
+        BOOST_TEST( pi->v == 1+2 );
+
+        pi.reset();
+
+        BOOST_TEST( X::instances == 0 );
+    }
+
+    {
+        boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator(), 1, 2, 3 );
+        boost::weak_ptr wp( pi );
+
+        BOOST_TEST( X::instances == 1 );
+        BOOST_TEST( pi.get() != 0 );
+        BOOST_TEST( pi->v == 1+2+3 );
+
+        pi.reset();
+
+        BOOST_TEST( X::instances == 0 );
+    }
+
+    {
+        boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator(), 1, 2, 3, 4 );
+        boost::weak_ptr wp( pi );
+
+        BOOST_TEST( X::instances == 1 );
+        BOOST_TEST( pi.get() != 0 );
+        BOOST_TEST( pi->v == 1+2+3+4 );
+
+        pi.reset();
+
+        BOOST_TEST( X::instances == 0 );
+    }
+
+    {
+        boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator(), 1, 2, 3, 4, 5 );
+        boost::weak_ptr wp( pi );
+
+        BOOST_TEST( X::instances == 1 );
+        BOOST_TEST( pi.get() != 0 );
+        BOOST_TEST( pi->v == 1+2+3+4+5 );
+
+        pi.reset();
+
+        BOOST_TEST( X::instances == 0 );
+    }
+
+    {
+        boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator(), 1, 2, 3, 4, 5, 6 );
+        boost::weak_ptr wp( pi );
+
+        BOOST_TEST( X::instances == 1 );
+        BOOST_TEST( pi.get() != 0 );
+        BOOST_TEST( pi->v == 1+2+3+4+5+6 );
+
+        pi.reset();
+
+        BOOST_TEST( X::instances == 0 );
+    }
+
+    {
+        boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator(), 1, 2, 3, 4, 5, 6, 7 );
+        boost::weak_ptr wp( pi );
+
+        BOOST_TEST( X::instances == 1 );
+        BOOST_TEST( pi.get() != 0 );
+        BOOST_TEST( pi->v == 1+2+3+4+5+6+7 );
+
+        pi.reset();
+
+        BOOST_TEST( X::instances == 0 );
+    }
+
+    {
+        boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator(), 1, 2, 3, 4, 5, 6, 7, 8 );
+        boost::weak_ptr wp( pi );
+
+        BOOST_TEST( X::instances == 1 );
+        BOOST_TEST( pi.get() != 0 );
+        BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8 );
+
+        pi.reset();
+
+        BOOST_TEST( X::instances == 0 );
+    }
+
+    {
+        boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator(), 1, 2, 3, 4, 5, 6, 7, 8, 9 );
+        boost::weak_ptr wp( pi );
+
+        BOOST_TEST( X::instances == 1 );
+        BOOST_TEST( pi.get() != 0 );
+        BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8+9 );
+
+        pi.reset();
+
+        BOOST_TEST( X::instances == 0 );
+    }
+
+    return boost::report_errors();
+}
+
+#else // !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+int main()
+{
+    return 0;
+}
+
+#endif
diff --git a/test/shared_ptr_alloc11_test.cpp b/test/shared_ptr_alloc11_test.cpp
new file mode 100644
index 0000000..c2b7d6a
--- /dev/null
+++ b/test/shared_ptr_alloc11_test.cpp
@@ -0,0 +1,116 @@
+#include 
+
+//  shared_ptr_alloc11_test.cpp
+//
+//  Test the allocator constructor with a C++11 minimal allocator
+//
+//  Copyright (c) 2005, 2014 Peter Dimov
+//
+//  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
+
+
+#include 
+#include 
+#include 
+#include 
+
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+template< class T > class cxx11_allocator
+{
+public:
+
+    typedef T value_type;
+
+    cxx11_allocator()
+    {
+    }
+
+    template< class Y > cxx11_allocator( cxx11_allocator const & )
+    {
+    }
+
+    T * allocate( std::size_t n )
+    {
+        return static_cast< T* >( ::operator new( n * sizeof( T ) ) );
+    }
+
+    void deallocate( T * p, std::size_t n )
+    {
+        ::operator delete( p );
+    }
+};
+
+//
+
+struct D;
+
+struct X
+{
+    static int instances;
+
+    X(): deleted_( false )
+    {
+        ++instances;
+    }
+
+    ~X()
+    {
+        BOOST_TEST( deleted_ );
+        --instances;
+    }
+
+private:
+
+    friend struct D;
+
+    bool deleted_;
+
+    X( X const & );
+    X & operator=( X const & );
+};
+
+int X::instances = 0;
+
+struct D
+{
+    void operator()( X * px ) const
+    {
+        px->deleted_ = true;
+        delete px;
+    }
+};
+
+int main()
+{
+    BOOST_TEST( X::instances == 0 );
+
+    boost::shared_ptr pv( new X, D(), cxx11_allocator() );
+
+    BOOST_TEST( X::instances == 1 );
+
+    pv.reset();
+
+    BOOST_TEST( X::instances == 0 );
+
+    pv.reset( new X, D(), cxx11_allocator() );
+
+    BOOST_TEST( X::instances == 1 );
+
+    pv.reset();
+
+    BOOST_TEST( X::instances == 0 );
+
+    return boost::report_errors();
+}
+
+#else // !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+int main()
+{
+    return 0;
+}
+
+#endif
diff --git a/test/shared_ptr_alloc2_test.cpp b/test/shared_ptr_alloc2_test.cpp
index 93f9d26..89a44bb 100644
--- a/test/shared_ptr_alloc2_test.cpp
+++ b/test/shared_ptr_alloc2_test.cpp
@@ -91,7 +91,7 @@ public:
         ::operator delete( p );
     }
 
-    pointer allocate( size_type n, void const * )
+    pointer allocate( size_type n, void const * = 0 )
     {
         T * p = static_cast< T* >( ::operator new( n * sizeof( T ) ) );
 
@@ -107,7 +107,7 @@ public:
 
     void construct( pointer p, T const & t )
     {
-        new( p ) T( t );
+        ::new( p ) T( t );
     }
 
     void destroy( pointer p )
diff --git a/test/shared_ptr_alloc3_test.cpp b/test/shared_ptr_alloc3_test.cpp
new file mode 100644
index 0000000..011e9cf
--- /dev/null
+++ b/test/shared_ptr_alloc3_test.cpp
@@ -0,0 +1,78 @@
+#include 
+
+//  shared_ptr_alloc3_test.cpp
+//
+//  Copyright (c) 2005, 2014 Peter Dimov
+//
+//  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
+
+
+#include 
+#include 
+#include 
+#include 
+
+//
+
+struct D;
+
+struct X
+{
+    static int instances;
+
+    X(): deleted_( false )
+    {
+        ++instances;
+    }
+
+    ~X()
+    {
+        BOOST_TEST( deleted_ );
+        --instances;
+    }
+
+private:
+
+    friend struct D;
+
+    bool deleted_;
+
+    X( X const & );
+    X & operator=( X const & );
+};
+
+int X::instances = 0;
+
+struct D
+{
+    void operator()( X * px ) const
+    {
+        px->deleted_ = true;
+        delete px;
+    }
+};
+
+int main()
+{
+    BOOST_TEST( X::instances == 0 );
+
+    boost::shared_ptr pv( new X, D(), std::allocator() );
+
+    BOOST_TEST( X::instances == 1 );
+
+    pv.reset();
+
+    BOOST_TEST( X::instances == 0 );
+
+    pv.reset( new X, D(), std::allocator() );
+
+    BOOST_TEST( X::instances == 1 );
+
+    pv.reset();
+
+    BOOST_TEST( X::instances == 0 );
+
+    return boost::report_errors();
+}

From 975d04ac62e20905c2be723d5d337383b5fec27d Mon Sep 17 00:00:00 2001
From: Peter Dimov 
Date: Wed, 5 Feb 2014 00:29:18 +0200
Subject: [PATCH 27/39] Merge Jamfile.v2 on git's insistence

---
 test/Jamfile.v2 | 1 +
 1 file changed, 1 insertion(+)

diff --git a/test/Jamfile.v2 b/test/Jamfile.v2
index d43f696..862d846 100644
--- a/test/Jamfile.v2
+++ b/test/Jamfile.v2
@@ -151,6 +151,7 @@ import testing ;
           [ run allocate_shared_array_esft_test.cpp ]
           [ run allocate_shared_array_noinit_test.cpp ]
           [ run allocate_shared_array_value_test.cpp ]
+          [ run allocate_shared_array_construct_test.cpp ]
 
           [ run make_unique_test.cpp ]
           [ run make_unique_args_test.cpp ]

From 3ac6dbbf08ac75b2c6ced01a7f2356389686d00d Mon Sep 17 00:00:00 2001
From: Glen Fernandes 
Date: Tue, 4 Feb 2014 14:57:34 -0800
Subject: [PATCH 28/39] Make detail::as_allocator template C++11 friendly

---
 .../smart_ptr/detail/array_allocator.hpp      | 25 +++++++++++++------
 .../boost/smart_ptr/detail/array_deleter.hpp  |  2 --
 2 files changed, 18 insertions(+), 9 deletions(-)

diff --git a/include/boost/smart_ptr/detail/array_allocator.hpp b/include/boost/smart_ptr/detail/array_allocator.hpp
index bac8984..5c6baf4 100644
--- a/include/boost/smart_ptr/detail/array_allocator.hpp
+++ b/include/boost/smart_ptr/detail/array_allocator.hpp
@@ -143,21 +143,32 @@ namespace boost {
 #endif
             }
 
-            void construct(pointer memory, const Y& value) {
 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
-                YT::construct(pair, memory, value);
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
+    !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)   
+            template
+            void construct(U* memory, Args&&... args) {
+                YT::construct(pair, memory, std::forward(args)...);
+            }
 #else
-                pair.construct(memory, value);
+            template
+            void construct(U* memory, const Y& value) {
+                YT::construct(pair, memory, value);
+            }
 #endif
+            template
+            void destroy(U* memory) {
+                YT::destroy(pair, memory);
+            }
+#else
+            void construct(pointer memory, const Y& value) {
+                pair.construct(memory, value);
             }
 
             void destroy(pointer memory) {
-#if !defined(BOOST_NO_CXX11_ALLOCATOR)
-                YT::destroy(pair, memory);
-#else
                 pair.destroy(memory);
-#endif
             }
+#endif
 
             template
             bool operator==(const as_allocator& other) const {
diff --git a/include/boost/smart_ptr/detail/array_deleter.hpp b/include/boost/smart_ptr/detail/array_deleter.hpp
index b4ed44f..5fd7e43 100644
--- a/include/boost/smart_ptr/detail/array_deleter.hpp
+++ b/include/boost/smart_ptr/detail/array_deleter.hpp
@@ -74,7 +74,6 @@ namespace boost {
             }
 
         private:
-
 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
             typedef typename std::allocator_traits::
                 template rebind_alloc TA;
@@ -314,7 +313,6 @@ namespace boost {
 #endif
             }
 
-        private:
             type* object;
         };
     }

From d229ae870ca9f3143deef7d0492cad7364f0d60f Mon Sep 17 00:00:00 2001
From: Peter Dimov 
Date: Wed, 5 Feb 2014 01:04:20 +0200
Subject: [PATCH 29/39] Subsume zero-argument overload into the variadic one

---
 .../boost/smart_ptr/make_shared_object.hpp    | 92 ++++++++++---------
 1 file changed, 48 insertions(+), 44 deletions(-)

diff --git a/include/boost/smart_ptr/make_shared_object.hpp b/include/boost/smart_ptr/make_shared_object.hpp
index 52a00ce..b0064ad 100644
--- a/include/boost/smart_ptr/make_shared_object.hpp
+++ b/include/boost/smart_ptr/make_shared_object.hpp
@@ -131,26 +131,7 @@ template< class T, std::size_t N > struct sp_if_not_array< T[N] >
 # define BOOST_SP_MSD( T ) boost::detail::sp_ms_deleter< T >()
 #endif
 
-// Zero-argument versions
-//
-// Used even when variadic templates are available because of the new T() vs new T issue
-
-template< class T > typename boost::detail::sp_if_not_array< T >::type make_shared()
-{
-    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
-
-    boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() );
-
-    void * pv = pd->address();
-
-    ::new( pv ) T();
-    pd->set_initialized();
-
-    T * pt2 = static_cast< T* >( pv );
-
-    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
-    return boost::shared_ptr< T >( pt, pt2 );
-}
+// _noinit versions
 
 template< class T > typename boost::detail::sp_if_not_array< T >::type make_shared_noinit()
 {
@@ -169,23 +150,6 @@ template< class T > typename boost::detail::sp_if_not_array< T >::type make_shar
     return boost::shared_ptr< T >( pt, pt2 );
 }
 
-template< class T, class A > typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a )
-{
-    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
-
-    boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() );
-
-    void * pv = pd->address();
-
-    ::new( pv ) T();
-    pd->set_initialized();
-
-    T * pt2 = static_cast< T* >( pv );
-
-    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
-    return boost::shared_ptr< T >( pt, pt2 );
-}
-
 template< class T, class A > typename boost::detail::sp_if_not_array< T >::type allocate_shared_noinit( A const & a )
 {
     boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
@@ -207,7 +171,7 @@ template< class T, class A > typename boost::detail::sp_if_not_array< T >::type
 
 // Variadic templates, rvalue reference
 
-template< class T, class Arg1, class... Args > typename boost::detail::sp_if_not_array< T >::type make_shared( Arg1 && arg1, Args && ... args )
+template< class T, class... Args > typename boost::detail::sp_if_not_array< T >::type make_shared( Args && ... args )
 {
     boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
 
@@ -215,7 +179,7 @@ template< class T, class Arg1, class... Args > typename boost::detail::sp_if_not
 
     void * pv = pd->address();
 
-    ::new( pv ) T( boost::detail::sp_forward( arg1 ), boost::detail::sp_forward( args )... );
+    ::new( pv ) T( boost::detail::sp_forward( args )... );
     pd->set_initialized();
 
     T * pt2 = static_cast< T* >( pv );
@@ -224,7 +188,7 @@ template< class T, class Arg1, class... Args > typename boost::detail::sp_if_not
     return boost::shared_ptr< T >( pt, pt2 );
 }
 
-template< class T, class A, class Arg1, class... Args > typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, Arg1 && arg1, Args && ... args )
+template< class T, class A, class... Args > typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, Args && ... args )
 {
     boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
 
@@ -232,7 +196,7 @@ template< class T, class A, class Arg1, class... Args > typename boost::detail::
 
     void * pv = pd->address();
 
-    ::new( pv ) T( boost::detail::sp_forward( arg1 ), boost::detail::sp_forward( args )... );
+    ::new( pv ) T( boost::detail::sp_forward( args )... );
     pd->set_initialized();
 
     T * pt2 = static_cast< T* >( pv );
@@ -241,7 +205,45 @@ template< class T, class A, class Arg1, class... Args > typename boost::detail::
     return boost::shared_ptr< T >( pt, pt2 );
 }
 
-#elif !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+#else // !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+// Common zero-argument versions
+
+template< class T > typename boost::detail::sp_if_not_array< T >::type make_shared()
+{
+    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ) );
+
+    boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() );
+
+    void * pv = pd->address();
+
+    ::new( pv ) T();
+    pd->set_initialized();
+
+    T * pt2 = static_cast< T* >( pv );
+
+    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
+    return boost::shared_ptr< T >( pt, pt2 );
+}
+
+template< class T, class A > typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a )
+{
+    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
+
+    boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() );
+
+    void * pv = pd->address();
+
+    ::new( pv ) T();
+    pd->set_initialized();
+
+    T * pt2 = static_cast< T* >( pv );
+
+    boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
+    return boost::shared_ptr< T >( pt, pt2 );
+}
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
 
 // For example MSVC 10.0
 
@@ -695,7 +697,7 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a,
     return boost::shared_ptr< T >( pt, pt2 );
 }
 
-#else
+#else // !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
 
 // C++03 version
 
@@ -1023,7 +1025,9 @@ typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a,
     return boost::shared_ptr< T >( pt, pt2 );
 }
 
-#endif
+#endif // !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+#endif // !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
 
 #undef BOOST_SP_MSD
 

From 9f5822f427a5676717f16692993b1dc6282dd011 Mon Sep 17 00:00:00 2001
From: Peter Dimov 
Date: Wed, 5 Feb 2014 02:31:33 +0200
Subject: [PATCH 30/39] Add support and test for C++11 construct/destroy in
 allocate_shared

---
 .../smart_ptr/detail/sp_counted_impl.hpp      |   2 +-
 .../boost/smart_ptr/make_shared_object.hpp    |  99 +++++++-
 test/Jamfile.v2                               |   1 +
 test/allocate_shared_construct11_test.cpp     | 240 ++++++++++++++++++
 4 files changed, 339 insertions(+), 3 deletions(-)
 create mode 100644 test/allocate_shared_construct11_test.cpp

diff --git a/include/boost/smart_ptr/detail/sp_counted_impl.hpp b/include/boost/smart_ptr/detail/sp_counted_impl.hpp
index 404f982..8702532 100644
--- a/include/boost/smart_ptr/detail/sp_counted_impl.hpp
+++ b/include/boost/smart_ptr/detail/sp_counted_impl.hpp
@@ -213,7 +213,7 @@ public:
     {
     }
 
-    sp_counted_impl_pda( P p, A a ): p_( p ), d_(), a_( a )
+    sp_counted_impl_pda( P p, A a ): p_( p ), d_( a ), a_( a )
     {
     }
 
diff --git a/include/boost/smart_ptr/make_shared_object.hpp b/include/boost/smart_ptr/make_shared_object.hpp
index b0064ad..62372fa 100644
--- a/include/boost/smart_ptr/make_shared_object.hpp
+++ b/include/boost/smart_ptr/make_shared_object.hpp
@@ -72,6 +72,10 @@ public:
     {
     }
 
+    template explicit sp_ms_deleter( A const & ) BOOST_NOEXCEPT : initialized_( false )
+    {
+    }
+
     // optimization: do not copy storage_
     sp_ms_deleter( sp_ms_deleter const & ) BOOST_NOEXCEPT : initialized_( false )
     {
@@ -102,6 +106,74 @@ public:
     }
 };
 
+template< class T, class A > class sp_as_deleter
+{
+private:
+
+    typedef typename sp_aligned_storage< sizeof( T ), ::boost::alignment_of< T >::value >::type storage_type;
+
+    storage_type storage_;
+    A a_;
+    bool initialized_;
+
+private:
+
+    void destroy()
+    {
+        if( initialized_ )
+        {
+            T * p = reinterpret_cast< T* >( storage_.data_ );
+
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+            std::allocator_traits::destroy( a_, p );
+
+#else
+
+            p->~T();
+
+#endif
+
+            initialized_ = false;
+        }
+    }
+
+public:
+
+    sp_as_deleter( A const & a ) BOOST_NOEXCEPT : a_( a ), initialized_( false )
+    {
+    }
+
+    // optimization: do not copy storage_
+    sp_as_deleter( sp_as_deleter const & r ) BOOST_NOEXCEPT : a_( r.a_), initialized_( false )
+    {
+    }
+
+    ~sp_as_deleter()
+    {
+        destroy();
+    }
+
+    void operator()( T * )
+    {
+        destroy();
+    }
+
+    static void operator_fn( T* ) // operator() can't be static
+    {
+    }
+
+    void * address() BOOST_NOEXCEPT
+    {
+        return storage_.data_;
+    }
+
+    void set_initialized() BOOST_NOEXCEPT
+    {
+        initialized_ = true;
+    }
+};
+
 template< class T > struct sp_if_not_array
 {
     typedef boost::shared_ptr< T > type;
@@ -190,13 +262,36 @@ template< class T, class... Args > typename boost::detail::sp_if_not_array< T >:
 
 template< class T, class A, class... Args > typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, Args && ... args )
 {
-    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
 
-    boost::detail::sp_ms_deleter< T > * pd = static_cast *>( pt._internal_get_untyped_deleter() );
+    typedef typename std::allocator_traits::template rebind_alloc A2;
+    A2 a2( a );
 
+    typedef boost::detail::sp_as_deleter< T, A2 > D;
+
+    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_inplace_tag(), a2 );
+
+#else
+
+    typedef boost::detail::sp_ms_deleter< T > D;
+
+    boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_inplace_tag(), a );
+
+#endif
+
+    D * pd = static_cast< D* >( pt._internal_get_untyped_deleter() );
     void * pv = pd->address();
 
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+    std::allocator_traits::construct( a2, static_cast< T* >( pv ), boost::detail::sp_forward( args )... );
+
+#else
+
     ::new( pv ) T( boost::detail::sp_forward( args )... );
+
+#endif
+
     pd->set_initialized();
 
     T * pt2 = static_cast< T* >( pv );
diff --git a/test/Jamfile.v2 b/test/Jamfile.v2
index 862d846..fc95688 100644
--- a/test/Jamfile.v2
+++ b/test/Jamfile.v2
@@ -82,6 +82,7 @@ import testing ;
           [ run shared_ptr_alloc3_test.cpp ]
           [ run shared_ptr_alloc11_test.cpp ]
           [ run allocate_shared_alloc11_test.cpp ]
+          [ run allocate_shared_construct11_test.cpp ]
 
           [ compile-fail array_fail_spa_sp_c.cpp ]
           [ compile-fail array_fail_sp_spa_c.cpp ]
diff --git a/test/allocate_shared_construct11_test.cpp b/test/allocate_shared_construct11_test.cpp
new file mode 100644
index 0000000..131b4cb
--- /dev/null
+++ b/test/allocate_shared_construct11_test.cpp
@@ -0,0 +1,240 @@
+// allocate_shared_construct11_test.cpp
+//
+// Test whether allocate_shared uses construct/destroy in C++11
+//
+// Copyright 2007-2009, 2014 Peter Dimov
+//
+// 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
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+template< class T > class cxx11_allocator
+{
+public:
+
+    typedef T value_type;
+
+    cxx11_allocator()
+    {
+    }
+
+    template< class Y > cxx11_allocator( cxx11_allocator const & )
+    {
+    }
+
+    T * allocate( std::size_t n )
+    {
+        return static_cast< T* >( ::operator new( n * sizeof( T ) ) );
+    }
+
+    void deallocate( T * p, std::size_t n )
+    {
+        ::operator delete( p );
+    }
+
+    template void construct( T * p, Args&&... args )
+    {
+        ::new( static_cast< void* >( p ) ) T( std::forward( args )... );
+    }
+
+    void destroy( T * p )
+    {
+        p->~T();
+    }
+};
+
+class X
+{
+private:
+
+    X( X const & );
+    X & operator=( X const & );
+
+    void * operator new( std::size_t n )
+    {
+        BOOST_ERROR( "private X::new called" );
+        return ::operator new( n );
+    }
+
+    void operator delete( void * p )
+    {
+        BOOST_ERROR( "private X::delete called" );
+        ::operator delete( p );
+    }
+
+public:
+
+    static int instances;
+
+    int v;
+
+protected:
+
+    explicit X( int a1 = 0, int a2 = 0, int a3 = 0, int a4 = 0, int a5 = 0, int a6 = 0, int a7 = 0, int a8 = 0, int a9 = 0 ): v( a1+a2+a3+a4+a5+a6+a7+a8+a9 )
+    {
+        ++instances;
+    }
+
+    ~X()
+    {
+        --instances;
+    }
+
+    friend class cxx11_allocator;
+};
+
+int X::instances = 0;
+
+int main()
+{
+    BOOST_TEST( X::instances == 0 );
+
+    {
+        boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator() );
+        boost::weak_ptr wp( pi );
+
+        BOOST_TEST( X::instances == 1 );
+        BOOST_TEST( pi.get() != 0 );
+        BOOST_TEST( pi->v == 0 );
+
+        pi.reset();
+
+        BOOST_TEST( X::instances == 0 );
+    }
+
+    {
+        boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator(), 1 );
+        boost::weak_ptr wp( pi );
+
+        BOOST_TEST( X::instances == 1 );
+        BOOST_TEST( pi.get() != 0 );
+        BOOST_TEST( pi->v == 1 );
+
+        pi.reset();
+
+        BOOST_TEST( X::instances == 0 );
+    }
+
+    {
+        boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator(), 1, 2 );
+        boost::weak_ptr wp( pi );
+
+        BOOST_TEST( X::instances == 1 );
+        BOOST_TEST( pi.get() != 0 );
+        BOOST_TEST( pi->v == 1+2 );
+
+        pi.reset();
+
+        BOOST_TEST( X::instances == 0 );
+    }
+
+    {
+        boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator(), 1, 2, 3 );
+        boost::weak_ptr wp( pi );
+
+        BOOST_TEST( X::instances == 1 );
+        BOOST_TEST( pi.get() != 0 );
+        BOOST_TEST( pi->v == 1+2+3 );
+
+        pi.reset();
+
+        BOOST_TEST( X::instances == 0 );
+    }
+
+    {
+        boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator(), 1, 2, 3, 4 );
+        boost::weak_ptr wp( pi );
+
+        BOOST_TEST( X::instances == 1 );
+        BOOST_TEST( pi.get() != 0 );
+        BOOST_TEST( pi->v == 1+2+3+4 );
+
+        pi.reset();
+
+        BOOST_TEST( X::instances == 0 );
+    }
+
+    {
+        boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator(), 1, 2, 3, 4, 5 );
+        boost::weak_ptr wp( pi );
+
+        BOOST_TEST( X::instances == 1 );
+        BOOST_TEST( pi.get() != 0 );
+        BOOST_TEST( pi->v == 1+2+3+4+5 );
+
+        pi.reset();
+
+        BOOST_TEST( X::instances == 0 );
+    }
+
+    {
+        boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator(), 1, 2, 3, 4, 5, 6 );
+        boost::weak_ptr wp( pi );
+
+        BOOST_TEST( X::instances == 1 );
+        BOOST_TEST( pi.get() != 0 );
+        BOOST_TEST( pi->v == 1+2+3+4+5+6 );
+
+        pi.reset();
+
+        BOOST_TEST( X::instances == 0 );
+    }
+
+    {
+        boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator(), 1, 2, 3, 4, 5, 6, 7 );
+        boost::weak_ptr wp( pi );
+
+        BOOST_TEST( X::instances == 1 );
+        BOOST_TEST( pi.get() != 0 );
+        BOOST_TEST( pi->v == 1+2+3+4+5+6+7 );
+
+        pi.reset();
+
+        BOOST_TEST( X::instances == 0 );
+    }
+
+    {
+        boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator(), 1, 2, 3, 4, 5, 6, 7, 8 );
+        boost::weak_ptr wp( pi );
+
+        BOOST_TEST( X::instances == 1 );
+        BOOST_TEST( pi.get() != 0 );
+        BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8 );
+
+        pi.reset();
+
+        BOOST_TEST( X::instances == 0 );
+    }
+
+    {
+        boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator(), 1, 2, 3, 4, 5, 6, 7, 8, 9 );
+        boost::weak_ptr wp( pi );
+
+        BOOST_TEST( X::instances == 1 );
+        BOOST_TEST( pi.get() != 0 );
+        BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8+9 );
+
+        pi.reset();
+
+        BOOST_TEST( X::instances == 0 );
+    }
+
+    return boost::report_errors();
+}
+
+#else // !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+int main()
+{
+    return 0;
+}
+
+#endif

From 540149f01986e70d79ffad5ad92148fda8953254 Mon Sep 17 00:00:00 2001
From: Glen Fernandes 
Date: Tue, 4 Feb 2014 22:45:58 -0800
Subject: [PATCH 31/39] Tidy documentation in smart_ptr

---
 compatibility.htm            |  172 ++---
 enable_shared_from_this.html |  106 ++-
 index.html                   |   13 +-
 intrusive_ptr.html           |  461 ++++++-------
 intrusive_ref_counter.html   |   21 +-
 make_shared.html             |  154 ++---
 make_shared_array.html       |    8 +-
 make_unique.html             |    2 +-
 pointer_cast.html            |   83 +--
 pointer_to_other.html        |   84 +--
 scoped_array.htm             |  183 +++--
 scoped_ptr.htm               |  271 ++++----
 shared_array.htm             |  276 ++++----
 shared_ptr.htm               | 1216 +++++++++++++++++-----------------
 smart_ptr.htm                |  431 ++++++------
 smarttests.htm               |   11 +-
 sp_techniques.html           |  574 ++++++++--------
 weak_ptr.htm                 |  332 +++++-----
 18 files changed, 2197 insertions(+), 2201 deletions(-)

diff --git a/compatibility.htm b/compatibility.htm
index d520bd1..6f57e4d 100644
--- a/compatibility.htm
+++ b/compatibility.htm
@@ -1,88 +1,88 @@
-
+
 
-	
-		Smart Pointer Changes
-		
-	
-	
-		

boost.png (6897 bytes)Smart Pointer Changes

-

The February 2002 change to the Boost smart pointers introduced a number of - changes. Since the previous version of the smart pointers was in use for a long - time, it's useful to have a detailed list of what changed from a library user's - point of view.

-

Note that for compilers that don't support member templates well enough, a - separate implementation is used that lacks many of the new features and is more - like the old version.

-

Features Requiring Code Changes to Take Advantage

-
    -
  • - The smart pointer class templates now each have their own header file. For - compatibility, the <boost/smart_ptr.hpp> - header now includes the headers for the four classic smart pointer class - templates. -
  • - The weak_ptr - template was added. -
  • - The new shared_ptr and shared_array relax the requirement that - the pointed-to object's destructor must be visible when instantiating the shared_ptr - destructor. This makes it easier to have shared_ptr members in classes without - explicit destructors. -
  • - A custom deallocator can be passed in when creating a shared_ptr or shared_array. -
  • - shared_static_cast and shared_dynamic_cast function templates are - provided which work for shared_ptr and weak_ptr as static_cast - and dynamic_cast - do for pointers. -
  • - The self-assignment misfeature has been removed from shared_ptr::reset, - although it is still present in scoped_ptr, and in std::auto_ptr. - Calling reset with a pointer to the object that's already owned by the shared_ptr - results in undefined behavior (an assertion, or eventually a double-delete if - assertions are off). -
  • - The BOOST_SMART_PTR_CONVERSION - feature has been removed. -
  • - shared_ptr<void> is now allowed.
  • -
-

Features That Improve Robustness

-
    -
  • - The manipulation of use counts is now thread safe on - Windows, Linux, and platforms that support pthreads. See the - <boost/detail/atomic_count.hpp> - file for details -
  • - The new shared_ptr will always delete the object using the pointer it was - originally constructed with. This prevents subtle problems that could happen if - the last shared_ptr was a pointer to a sub-object of a class that did - not have a virtual destructor.
  • -
-

Implementation Details

-
    -
  • - Some bugs in the assignment operator implementations and in reset - have been fixed by using the "copy and swap" idiom. -
  • - Assertions have been added to check preconditions of various functions; - however, since these use the new <boost/assert.hpp> - header, the assertions are disabled by default. -
  • - The partial specialization of std::less has been replaced by operator< - overloads which accomplish the same thing without relying on undefined - behavior. -
  • - The incorrect overload of std::swap has been replaced by boost::swap, - which has many of the same advantages for generic programming but does not - violate the C++ standard.
  • -
-
-

Revised 1 February 2002

-

Copyright 2002 Darin Adler. 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.

- + + Smart Pointer Changes + + + +

boost.png (6897 bytes)Smart Pointer Changes

+

The February 2002 change to the Boost smart pointers introduced a number of + changes. Since the previous version of the smart pointers was in use for a long + time, it's useful to have a detailed list of what changed from a library user's + point of view.

+

Note that for compilers that don't support member templates well enough, a + separate implementation is used that lacks many of the new features and is more + like the old version.

+

Features Requiring Code Changes to Take Advantage

+
    +
  • + The smart pointer class templates now each have their own header file. For + compatibility, the <boost/smart_ptr.hpp> + header now includes the headers for the four classic smart pointer class + templates. +
  • + The weak_ptr + template was added. +
  • + The new shared_ptr and shared_array relax the requirement that + the pointed-to object's destructor must be visible when instantiating the shared_ptr + destructor. This makes it easier to have shared_ptr members in classes without + explicit destructors. +
  • + A custom deallocator can be passed in when creating a shared_ptr or shared_array. +
  • + shared_static_cast and shared_dynamic_cast function templates are + provided which work for shared_ptr and weak_ptr as static_cast + and dynamic_cast + do for pointers. +
  • + The self-assignment misfeature has been removed from shared_ptr::reset, + although it is still present in scoped_ptr, and in std::auto_ptr. + Calling reset with a pointer to the object that's already owned by the shared_ptr + results in undefined behavior (an assertion, or eventually a double-delete if + assertions are off). +
  • + The BOOST_SMART_PTR_CONVERSION + feature has been removed. +
  • + shared_ptr<void> is now allowed.
  • +
+

Features That Improve Robustness

+
    +
  • + The manipulation of use counts is now thread safe on + Windows, Linux, and platforms that support pthreads. See the + <boost/detail/atomic_count.hpp> + file for details +
  • + The new shared_ptr will always delete the object using the pointer it was + originally constructed with. This prevents subtle problems that could happen if + the last shared_ptr was a pointer to a sub-object of a class that did + not have a virtual destructor.
  • +
+

Implementation Details

+
    +
  • + Some bugs in the assignment operator implementations and in reset + have been fixed by using the "copy and swap" idiom. +
  • + Assertions have been added to check preconditions of various functions; + however, since these use the new <boost/assert.hpp> + header, the assertions are disabled by default. +
  • + The partial specialization of std::less has been replaced by operator< + overloads which accomplish the same thing without relying on undefined + behavior. +
  • + The incorrect overload of std::swap has been replaced by boost::swap, + which has many of the same advantages for generic programming but does not + violate the C++ standard.
  • +
+
+

$Date$

+

Copyright 2002 Darin Adler. 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.

+ diff --git a/enable_shared_from_this.html b/enable_shared_from_this.html index c4caa25..028cf57 100644 --- a/enable_shared_from_this.html +++ b/enable_shared_from_this.html @@ -1,34 +1,24 @@ - + - - Boost: enable_shared_from_this.hpp documentation - - - -
- - - - - - - -
boost.png (6897 bytes) - -

enable_shared_from_this.hpp

-
 
-

Purpose

-

- The header <boost/enable_shared_from_this.hpp> defines - the class template enable_shared_from_this. It is used as a - base class that allows a shared_ptr to the current - object to be obtained from within a member function. -

-

enable_shared_from_this<T> defines two member functions - called shared_from_this that return a shared_ptr<T> - and shared_ptr<T const>, depending on constness, to this.

-

Example

-
+    
+        enable_shared_from_this
+        
+    
+    
+        

boost.png (6897 bytes)enable_shared_from_this

+

Purpose

+

+ The header <boost/enable_shared_from_this.hpp> defines + the class template enable_shared_from_this. It is used as a + base class that allows a shared_ptr to the current + object to be obtained from within a member function. +

+

enable_shared_from_this<T> defines two member functions + called shared_from_this that return a shared_ptr<T> + and shared_ptr<T const>, depending on constness, to this.

+

Example

+
 #include <boost/enable_shared_from_this.hpp>
 #include <boost/shared_ptr.hpp>
 #include <cassert>
@@ -51,8 +41,8 @@ int main()
     assert(!(p < q || q < p)); // p and q must share ownership
 }
 
-

Synopsis

-
+        

Synopsis

+
 namespace boost
 {
 
@@ -66,30 +56,30 @@ public:
 
 }
 
-

template<class T> shared_ptr<T> - enable_shared_from_this<T>::shared_from_this();

-

template<class T> shared_ptr<T const> - enable_shared_from_this<T>::shared_from_this() const;

-
-

- Requires: enable_shared_from_this<T> must be an - accessible base class of T. *this must be a subobject - of an instance t of type T . There must exist - at least one shared_ptr instance p that owns - t. -

-

- Returns: A shared_ptr<T> instance r that shares - ownership with p. -

-

- Postconditions: r.get() == this. -

-
-

-
- Copyright © 2002, 2003 by Peter Dimov. 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.

- +

template<class T> shared_ptr<T> + enable_shared_from_this<T>::shared_from_this();

+

template<class T> shared_ptr<T const> + enable_shared_from_this<T>::shared_from_this() const;

+
+

+ Requires: enable_shared_from_this<T> must be an + accessible base class of T. *this must be a subobject + of an instance t of type T . There must exist + at least one shared_ptr instance p that owns + t. +

+

+ Returns: A shared_ptr<T> instance r that shares + ownership with p. +

+

+ Postconditions: r.get() == this. +

+
+

$Date$

+

+ Copyright © 2002, 2003 by Peter Dimov. 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.

+ diff --git a/index.html b/index.html index c7f709c..0551e3c 100644 --- a/index.html +++ b/index.html @@ -1,15 +1,18 @@ + +Smart Pointers + - + Automatic redirection failed, please go to smart_ptr.htm. diff --git a/intrusive_ptr.html b/intrusive_ptr.html index d5d162f..df969dd 100644 --- a/intrusive_ptr.html +++ b/intrusive_ptr.html @@ -1,51 +1,51 @@ - + - - intrusive_ptr - - - -

boost.png (6897 bytes)intrusive_ptr class template

-

- Introduction
- Synopsis
- Members
- Free Functions
-

-

Introduction

-

The intrusive_ptr class template stores a pointer to an object with an - embedded reference count. Every new intrusive_ptr instance increments - the reference count by using an unqualified call to the function intrusive_ptr_add_ref, - passing it the pointer as an argument. Similarly, when an intrusive_ptr - is destroyed, it calls intrusive_ptr_release; this function is - responsible for destroying the object when its reference count drops to zero. - The user is expected to provide suitable definitions of these two functions. On - compilers that support argument-dependent lookup, intrusive_ptr_add_ref - and intrusive_ptr_release should be defined in the namespace - that corresponds to their parameter; otherwise, the definitions need to go in - namespace boost. The library provides a helper base class template - intrusive_ref_counter which may - help adding support for intrusive_ptr to user types.

-

The class template is parameterized on T, the type of the object pointed - to. intrusive_ptr<T> can be implicitly converted to intrusive_ptr<U> - whenever T* can be implicitly converted to U*.

-

The main reasons to use intrusive_ptr are:

-
    -
  • - Some existing frameworks or OSes provide objects with embedded reference - counts;
  • -
  • - The memory footprint of intrusive_ptr - is the same as the corresponding raw pointer;
  • -
  • - intrusive_ptr<T> can be constructed from an arbitrary - raw pointer of type T *.
-

As a general rule, if it isn't obvious whether intrusive_ptr better - fits your needs than shared_ptr, try a shared_ptr-based - design first.

-

Synopsis

-
namespace boost {
+    
+        intrusive_ptr
+        
+    
+    
+        

boost.png (6897 bytes)intrusive_ptr class template

+

+ Introduction
+ Synopsis
+ Members
+ Free Functions
+

+

Introduction

+

The intrusive_ptr class template stores a pointer to an object with an + embedded reference count. Every new intrusive_ptr instance increments + the reference count by using an unqualified call to the function intrusive_ptr_add_ref, + passing it the pointer as an argument. Similarly, when an intrusive_ptr + is destroyed, it calls intrusive_ptr_release; this function is + responsible for destroying the object when its reference count drops to zero. + The user is expected to provide suitable definitions of these two functions. On + compilers that support argument-dependent lookup, intrusive_ptr_add_ref + and intrusive_ptr_release should be defined in the namespace + that corresponds to their parameter; otherwise, the definitions need to go in + namespace boost. The library provides a helper base class template + intrusive_ref_counter which may + help adding support for intrusive_ptr to user types.

+

The class template is parameterized on T, the type of the object pointed + to. intrusive_ptr<T> can be implicitly converted to intrusive_ptr<U> + whenever T* can be implicitly converted to U*.

+

The main reasons to use intrusive_ptr are:

+
    +
  • + Some existing frameworks or OSes provide objects with embedded reference + counts;
  • +
  • + The memory footprint of intrusive_ptr + is the same as the corresponding raw pointer;
  • +
  • + intrusive_ptr<T> can be constructed from an arbitrary + raw pointer of type T *.
+

As a general rule, if it isn't obvious whether intrusive_ptr better + fits your needs than shared_ptr, try a shared_ptr-based + design first.

+

Synopsis

+
namespace boost {
 
   template<class T> class intrusive_ptr {
 
@@ -117,203 +117,204 @@
     std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, intrusive_ptr<Y> const & p);
 
 }
-

Members

-

element_type

-
typedef T element_type;
-
-

Provides the type of the template parameter T.

-
-

constructors

-
intrusive_ptr(); // never throws
-
-

Postconditions: get() == 0.

-

Throws: nothing.

-
-
intrusive_ptr(T * p, bool add_ref = true);
-
-

Effects: if(p != 0 && add_ref) intrusive_ptr_add_ref(p);.

-

Postconditions: get() == p.

-
-
intrusive_ptr(intrusive_ptr const & r);
+        

Members

+

element_type

+
typedef T element_type;
+
+

Provides the type of the template parameter T.

+
+

constructors

+
intrusive_ptr(); // never throws
+
+

Postconditions: get() == 0.

+

Throws: nothing.

+
+
intrusive_ptr(T * p, bool add_ref = true);
+
+

Effects: if(p != 0 && add_ref) intrusive_ptr_add_ref(p);.

+

Postconditions: get() == p.

+
+
intrusive_ptr(intrusive_ptr const & r);
 template<class Y> intrusive_ptr(intrusive_ptr<Y> const & r);
-
-

Effects: if(r.get() != 0) intrusive_ptr_add_ref(r.get());.

-

Postconditions: get() == r.get().

-
-

destructor

-
~intrusive_ptr();
-
-

Effects: if(get() != 0) intrusive_ptr_release(get());.

-
-

assignment

-
intrusive_ptr & operator=(intrusive_ptr const & r);
+        
+

Effects: if(r.get() != 0) intrusive_ptr_add_ref(r.get());.

+

Postconditions: get() == r.get().

+
+

destructor

+
~intrusive_ptr();
+
+

Effects: if(get() != 0) intrusive_ptr_release(get());.

+
+

assignment

+
intrusive_ptr & operator=(intrusive_ptr const & r);
 template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r);
 intrusive_ptr & operator=(T * r);
-
-

Effects: Equivalent to intrusive_ptr(r).swap(*this).

-

Returns: *this.

-
-

reset

-
void reset();
-
-

Effects: Equivalent to intrusive_ptr().swap(*this).

-
-
void reset(T * r);
-
-

Effects: Equivalent to intrusive_ptr(r).swap(*this).

-
-
void reset(T * r, bool add_ref);
-
-

Effects: Equivalent to intrusive_ptr(r, add_ref).swap(*this).

-
-

indirection

-
T & operator*() const; // never throws
-
-

Requirements: get() != 0.

-

Returns: *get().

-

Throws: nothing.

-
-
T * operator->() const; // never throws
-
-

Requirements: get() != 0.

-

Returns: get().

-

Throws: nothing.

-
-

get

-
T * get() const; // never throws
-
-

Returns: the stored pointer.

-

Throws: nothing.

-
-

detach

-
T * detach(); // never throws
-
-

Returns: the stored pointer.

-

Throws: nothing.

-

Postconditions: get() == 0.

-

Notes: The returned pointer has an elevated reference count. This - allows conversion of an intrusive_ptr back to a raw pointer, - without the performance overhead of acquiring and dropping an extra - reference. It can be viewed as the complement of the - non-reference-incrementing constructor.

-

Caution: Using detach escapes the safety of automatic - reference counting provided by intrusive_ptr. It should - by used only where strictly necessary (such as when interfacing to an - existing API), and when the implications are thoroughly understood.

-
-

conversions

-
operator unspecified-bool-type () const; // never throws
-
-

Returns: an unspecified value that, when used in boolean contexts, is - equivalent to get() != 0.

-

Throws: nothing.

-

Notes: This conversion operator allows intrusive_ptr objects to be - used in boolean contexts, like if (p && p->valid()) {}. - The actual target type is typically a pointer to a member function, avoiding - many of the implicit conversion pitfalls.

-
-

swap

-
void swap(intrusive_ptr & b); // never throws
-
-

Effects: Exchanges the contents of the two smart pointers.

-

Throws: nothing.

-
-

Free Functions

-

comparison

-
template<class T, class U>
+        
+

Effects: Equivalent to intrusive_ptr(r).swap(*this).

+

Returns: *this.

+
+

reset

+
void reset();
+
+

Effects: Equivalent to intrusive_ptr().swap(*this).

+
+
void reset(T * r);
+
+

Effects: Equivalent to intrusive_ptr(r).swap(*this).

+
+
void reset(T * r, bool add_ref);
+
+

Effects: Equivalent to intrusive_ptr(r, add_ref).swap(*this).

+
+

indirection

+
T & operator*() const; // never throws
+
+

Requirements: get() != 0.

+

Returns: *get().

+

Throws: nothing.

+
+
T * operator->() const; // never throws
+
+

Requirements: get() != 0.

+

Returns: get().

+

Throws: nothing.

+
+

get

+
T * get() const; // never throws
+
+

Returns: the stored pointer.

+

Throws: nothing.

+
+

detach

+
T * detach(); // never throws
+
+

Returns: the stored pointer.

+

Throws: nothing.

+

Postconditions: get() == 0.

+

Notes: The returned pointer has an elevated reference count. This + allows conversion of an intrusive_ptr back to a raw pointer, + without the performance overhead of acquiring and dropping an extra + reference. It can be viewed as the complement of the + non-reference-incrementing constructor.

+

Caution: Using detach escapes the safety of automatic + reference counting provided by intrusive_ptr. It should + by used only where strictly necessary (such as when interfacing to an + existing API), and when the implications are thoroughly understood.

+
+

conversions

+
operator unspecified-bool-type () const; // never throws
+
+

Returns: an unspecified value that, when used in boolean contexts, is + equivalent to get() != 0.

+

Throws: nothing.

+

Notes: This conversion operator allows intrusive_ptr objects to be + used in boolean contexts, like if (p && p->valid()) {}. + The actual target type is typically a pointer to a member function, avoiding + many of the implicit conversion pitfalls.

+
+

swap

+
void swap(intrusive_ptr & b); // never throws
+
+

Effects: Exchanges the contents of the two smart pointers.

+

Throws: nothing.

+
+

Free Functions

+

comparison

+
template<class T, class U>
   bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b); // never throws
-
-

Returns: a.get() == b.get().

-

Throws: nothing.

-
-
template<class T, class U>
+        
+

Returns: a.get() == b.get().

+

Throws: nothing.

+
+
template<class T, class U>
   bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b); // never throws
-
-

Returns: a.get() != b.get().

-

Throws: nothing.

-
-
template<class T, class U>
+        
+

Returns: a.get() != b.get().

+

Throws: nothing.

+
+
template<class T, class U>
   bool operator==(intrusive_ptr<T> const & a, U * b); // never throws
-
-

Returns: a.get() == b.

-

Throws: nothing.

-
-
template<class T, class U>
+        
+

Returns: a.get() == b.

+

Throws: nothing.

+
+
template<class T, class U>
   bool operator!=(intrusive_ptr<T> const & a, U * b); // never throws
-
-

Returns: a.get() != b.

-

Throws: nothing.

-
-
template<class T, class U>
+        
+

Returns: a.get() != b.

+

Throws: nothing.

+
+
template<class T, class U>
   bool operator==(T * a, intrusive_ptr<U> const & b); // never throws
-
-

Returns: a == b.get().

-

Throws: nothing.

-
-
template<class T, class U>
+        
+

Returns: a == b.get().

+

Throws: nothing.

+
+
template<class T, class U>
   bool operator!=(T * a, intrusive_ptr<U> const & b); // never throws
-
-

Returns: a != b.get().

-

Throws: nothing.

-
-
template<class T, class U>
+        
+

Returns: a != b.get().

+

Throws: nothing.

+
+
template<class T, class U>
   bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b); // never throws
-
-

Returns: std::less<T *>()(a.get(), b.get()).

-

Throws: nothing.

-

Notes: Allows intrusive_ptr objects to be used as keys - in associative containers.

-
-

swap

-
template<class T>
+        
+

Returns: std::less<T *>()(a.get(), b.get()).

+

Throws: nothing.

+

Notes: Allows intrusive_ptr objects to be used as keys + in associative containers.

+
+

swap

+
template<class T>
   void swap(intrusive_ptr<T> & a, intrusive_ptr<T> & b); // never throws
-
-

Effects: Equivalent to a.swap(b).

-

Throws: nothing.

-

Notes: Matches the interface of std::swap. Provided as an aid to - generic programming.

-
-

get_pointer

-
template<class T>
+        
+

Effects: Equivalent to a.swap(b).

+

Throws: nothing.

+

Notes: Matches the interface of std::swap. Provided as an aid to + generic programming.

+
+

get_pointer

+
template<class T>
   T * get_pointer(intrusive_ptr<T> const & p); // never throws
-
-

Returns: p.get().

-

Throws: nothing.

-

Notes: Provided as an aid to generic programming. Used by - mem_fn.

-
-

static_pointer_cast

-
template<class T, class U>
+        
+

Returns: p.get().

+

Throws: nothing.

+

Notes: Provided as an aid to generic programming. Used by + mem_fn.

+
+

static_pointer_cast

+
template<class T, class U>
   intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & r); // never throws
-
-

Returns: intrusive_ptr<T>(static_cast<T*>(r.get())).

-

Throws: nothing.

-
-

const_pointer_cast

-
template<class T, class U>
+        
+

Returns: intrusive_ptr<T>(static_cast<T*>(r.get())).

+

Throws: nothing.

+
+

const_pointer_cast

+
template<class T, class U>
   intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & r); // never throws
-
-

Returns: intrusive_ptr<T>(const_cast<T*>(r.get())).

-

Throws: nothing.

-
-

dynamic_pointer_cast

-
template<class T, class U>
+        
+

Returns: intrusive_ptr<T>(const_cast<T*>(r.get())).

+

Throws: nothing.

+
+

dynamic_pointer_cast

+
template<class T, class U>
   intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & r);
-
-

Returns: intrusive_ptr<T>(dynamic_cast<T*>(r.get())).

-

Throws: nothing.

-
-

operator<<

-
template<class E, class T, class Y>
+        
+

Returns: intrusive_ptr<T>(dynamic_cast<T*>(r.get())).

+

Throws: nothing.

+
+

operator<<

+
template<class E, class T, class Y>
     std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, intrusive_ptr<Y> const & p);
-
-

Effects: os << p.get();.

-

Returns: os.

-
-
-

- Copyright © 2003-2005, 2013 Peter Dimov. 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.

- +
+

Effects: os << p.get();.

+

Returns: os.

+
+
+

$Date$

+

+ Copyright © 2003-2005, 2013 Peter Dimov. 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.

+ diff --git a/intrusive_ref_counter.html b/intrusive_ref_counter.html index 72a46e0..f98227a 100644 --- a/intrusive_ref_counter.html +++ b/intrusive_ref_counter.html @@ -1,12 +1,12 @@ - + intrusive_ref_counter - -

boost.png (6897 bytes)basic_intrusive_ref_counter class template

+ +

boost.png (6897 bytes)basic_intrusive_ref_counter class template

Introduction
Synopsis
@@ -14,11 +14,11 @@

Introduction

The intrusive_ref_counter class template implements a reference counter for a derived - user's class that is intended to be used with intrusive_ptr. + user's class that is intended to be used with intrusive_ptr. The base class has associated intrusive_ptr_add_ref and intrusive_ptr_release functions which modify the reference counter as needed and destroy the user's object when the counter drops to zero.

The class template is parameterized on DerivedT and CounterPolicyT parameters. - The first parameter is the user's class that derives from intrusive_ref_counter. This type + The first parameter is the user's class that derives from intrusive_ref_counter. This type is needed in order to destroy the object correctly when there are no references to it left.

The second parameter is a policy that defines the nature of the reference counter. Boost.SmartPtr provides two such policies: thread_unsafe_counter and thread_safe_counter. The former @@ -85,11 +85,10 @@

Notes: The returned value may not be actual in multi-threaded applications.


+

$Date$

- $Date$

-

- Copyright © 2013 Andrey Semashev. 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.

+ Copyright © 2013 Andrey Semashev. 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.

diff --git a/make_shared.html b/make_shared.html index e2335d3..76a2ad8 100644 --- a/make_shared.html +++ b/make_shared.html @@ -1,37 +1,38 @@ - + - - make_shared and allocate_shared - - - -

boost.png (6897 bytes)make_shared and allocate_shared function templates

-

Introduction
- Synopsis
- Free Functions
- Example
-

Introduction

-

Consistent use of shared_ptr - can eliminate the need to use an explicit delete, - but alone it provides no support in avoiding explicit new. - There have been repeated requests from users for a factory function that creates - an object of a given type and returns a shared_ptr to it. - Besides convenience and style, such a function is also exception safe and - considerably faster because it can use a single allocation for both the object - and its corresponding control block, eliminating a significant portion of - shared_ptr's construction overhead. - This eliminates one of the major efficiency complaints about shared_ptr. -

-

The header file <boost/make_shared.hpp> provides a family of overloaded function templates, - make_shared and allocate_shared, to address this need. - make_shared uses the global operator new to allocate memory, - whereas allocate_shared uses an user-supplied allocator, allowing finer control.

-

- The rationale for choosing the name make_shared is that the expression - make_shared<Widget>() can be read aloud and conveys the intended meaning.

-

Synopsis

-
namespace boost {
+    
+        make_shared and allocate_shared
+        
+    
+    
+        

boost.png (6897 bytes)make_shared and allocate_shared + function templates

+

Introduction
+ Synopsis
+ Free Functions
+ Example
+

Introduction

+

Consistent use of shared_ptr + can eliminate the need to use an explicit delete, + but alone it provides no support in avoiding explicit new. + There have been repeated requests from users for a factory function that creates + an object of a given type and returns a shared_ptr to it. + Besides convenience and style, such a function is also exception safe and + considerably faster because it can use a single allocation for both the object + and its corresponding control block, eliminating a significant portion of + shared_ptr's construction overhead. + This eliminates one of the major efficiency complaints about shared_ptr. +

+

The header file <boost/make_shared.hpp> provides a family of overloaded function templates, + make_shared and allocate_shared, to address this need. + make_shared uses the global operator new to allocate memory, + whereas allocate_shared uses an user-supplied allocator, allowing finer control.

+

+ The rationale for choosing the name make_shared is that the expression + make_shared<Widget>() can be read aloud and conveys the intended meaning.

+

Synopsis

+
namespace boost {
 
   template<typename T> class shared_ptr;
 
@@ -41,7 +42,7 @@
   template<typename T, typename A>
     shared_ptr<T> allocate_shared( A const & );
 
-#if !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )	// C++0x prototypes
+#if !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )    // C++0x prototypes
 
   template<typename T, typename... Args>
     shared_ptr<T> make_shared( Args && ... args );
@@ -69,51 +70,50 @@
 
 #endif
 }
-

Free Functions

-
template<class T, class... Args>
+        

Free Functions

+
template<class T, class... Args>
     shared_ptr<T> make_shared( Args && ... args );
 template<class T, class A, class... Args>
     shared_ptr<T> allocate_shared( A const & a, Args && ... args );
-
-

Requires: The expression new( pv ) T( std::forward<Args>(args)... ), - where pv is a void* pointing to storage suitable - to hold an object of type T, - shall be well-formed. A shall be an Allocator, - as described in section 20.1.5 (Allocator requirements) of the C++ Standard. - The copy constructor and destructor of A shall not throw.

-

Effects: Allocates memory suitable for an object of type T - and constructs an object in it via the placement new expression new( pv ) T() - or new( pv ) T( std::forward<Args>(args)... ). - allocate_shared uses a copy of a to allocate memory. - If an exception is thrown, has no effect.

-

Returns: A shared_ptr instance that stores and owns the address - of the newly constructed object of type T.

-

Postconditions: get() != 0 && use_count() == 1.

-

Throws: bad_alloc, or an exception thrown from A::allocate - or the constructor of T.

-

Notes: This implementation allocates the memory required for the - returned shared_ptr and an object of type T in a single - allocation. This provides efficiency equivalent to an intrusive smart pointer.

-

The prototypes shown above are used if your compiler supports rvalue references - and variadic templates. They perfectly forward the args parameters to - the constructors of T.

-

Otherwise, the implementation will fall back on - forwarding the arguments to the constructors of T as const references. - If you need to pass a non-const reference to a constructor of T, - you may do so by wrapping the parameter in a call to boost::ref. - In addition, you will be - limited to a maximum of 9 arguments (not counting the allocator argument of - allocate_shared).

-
-

Example

-
boost::shared_ptr<std::string> x = boost::make_shared<std::string>("hello, world!");
+        
+

Requires: The expression new( pv ) T( std::forward<Args>(args)... ), + where pv is a void* pointing to storage suitable + to hold an object of type T, + shall be well-formed. A shall be an Allocator, + as described in section 20.1.5 (Allocator requirements) of the C++ Standard. + The copy constructor and destructor of A shall not throw.

+

Effects: Allocates memory suitable for an object of type T + and constructs an object in it via the placement new expression new( pv ) T() + or new( pv ) T( std::forward<Args>(args)... ). + allocate_shared uses a copy of a to allocate memory. + If an exception is thrown, has no effect.

+

Returns: A shared_ptr instance that stores and owns the address + of the newly constructed object of type T.

+

Postconditions: get() != 0 && use_count() == 1.

+

Throws: bad_alloc, or an exception thrown from A::allocate + or the constructor of T.

+

Notes: This implementation allocates the memory required for the + returned shared_ptr and an object of type T in a single + allocation. This provides efficiency equivalent to an intrusive smart pointer.

+

The prototypes shown above are used if your compiler supports rvalue references + and variadic templates. They perfectly forward the args parameters to + the constructors of T.

+

Otherwise, the implementation will fall back on + forwarding the arguments to the constructors of T as const references. + If you need to pass a non-const reference to a constructor of T, + you may do so by wrapping the parameter in a call to boost::ref. + In addition, you will be + limited to a maximum of 9 arguments (not counting the allocator argument of + allocate_shared).

+
+

Example

+
boost::shared_ptr<std::string> x = boost::make_shared<std::string>("hello, world!");
 std::cout << *x;
-
-

- $Date: 2008-05-19 15:42:39 -0400 (Mon, 19 May 2008) $

-

Copyright 2008 Peter Dimov. Copyright 2008 Frank Mori Hess. - 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.

- +
+

$Date$

+

Copyright 2008 Peter Dimov. Copyright 2008 Frank Mori Hess. + 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.

+ diff --git a/make_shared_array.html b/make_shared_array.html index 28a7a11..6c323b8 100644 --- a/make_shared_array.html +++ b/make_shared_array.html @@ -250,8 +250,10 @@ boost::shared_ptr<int[4][2]> a2 = boost::make_shared_noinit<int[4][2]&g

History

-

January 2014. Glen Fernandes reduced the overloads of make_shared and - allocate_shared according to N3870.

+

February 2014. Glen Fernandes updated overloads of make_shared and + allocate_shared to conform to the specification in C++ standard paper + N3870 including resolving C++ standard library + defect report 2070.

November 2012. Glen Fernandes contributed implementations of make_shared and allocate_shared for arrays.

References

@@ -260,7 +262,7 @@ boost::shared_ptr<int[4][2]> a2 = boost::make_shared_noinit<int[4][2]&g Extending make_shared to Support Arrays, Revision 1, Peter Dimov & Glen Fernandes, January, 2014.


-

$Date: 2014-01-20 11:10:00 -0800 (Mon, 20 Jan 2014) $

+

$Date$

Copyright 2012-2014 Glen Fernandes. Distributed under the Boost Software License, Version 1.0. See accompanying file LICENSE_1_0.txt or copy at diff --git a/make_unique.html b/make_unique.html index f1246db..c3e6ab8 100644 --- a/make_unique.html +++ b/make_unique.html @@ -142,7 +142,7 @@ unique_ptr<int[][2]> p2 = boost::make_unique_noinit<int[][2]>(2);

January 2014. Glen Fernandes contributed implementations of make_unique for objects and arrays.


-

$Date: 2014-01-20 11:10:00 -0800 (Mon, 20 Jan 2014) $

+

$Date$

Copyright 2012-2014 Glen Fernandes. Distributed under the Boost Software License, Version 1.0. See accompanying file LICENSE_1_0.txt or copy at diff --git a/pointer_cast.html b/pointer_cast.html index 8f14795..2ab0859 100644 --- a/pointer_cast.html +++ b/pointer_cast.html @@ -1,33 +1,34 @@ - + - - pointer_cast.hpp - - -

C++ BoostPointer - cast functions

-

The pointer cast functions (boost::static_pointer_cast boost::dynamic_pointer_cast - boost::reinterpret_pointer_cast boost::const_pointer_cast) - provide a way to write generic pointer castings for raw pointers. The functions - are defined in boost/pointer_cast.hpp.

-

There is test/example code in pointer_cast_test.cpp.

-

Rationale

-

Boost smart pointers usually overload those functions to provide a mechanism to - emulate pointers casts. For example, boost::shared_ptr<...> implements - a static pointer cast this way:

-
+    
+        pointer_cast
+        
+    
+    
+        

boost.png (6897 bytes)pointer_cast

+

The pointer cast functions (boost::static_pointer_cast boost::dynamic_pointer_cast + boost::reinterpret_pointer_cast boost::const_pointer_cast) + provide a way to write generic pointer castings for raw pointers. The functions + are defined in boost/pointer_cast.hpp.

+

There is test/example code in pointer_cast_test.cpp.

+

Rationale

+

Boost smart pointers usually overload those functions to provide a mechanism to + emulate pointers casts. For example, boost::shared_ptr<...> implements + a static pointer cast this way:

+
 template<class T, class U>
     shared_ptr<T> static_pointer_cast(shared_ptr<U> const &r);
 
-

Pointer cast functions from boost/pointer_cast.hpp - are overloads of boost::static_pointer_cast, boost::dynamic_pointer_cast, - boost::reinterpret_pointer_cast and boost::const_pointer_cast - for raw pointers. This way when developing pointer type independent classes, - for example, memory managers or shared memory compatible classes, the same code - can be used for raw and smart pointers.

-

Synopsis

-
-
+        

Pointer cast functions from boost/pointer_cast.hpp + are overloads of boost::static_pointer_cast, boost::dynamic_pointer_cast, + boost::reinterpret_pointer_cast and boost::const_pointer_cast + for raw pointers. This way when developing pointer type independent classes, + for example, memory managers or shared memory compatible classes, the same code + can be used for raw and smart pointers.

+

Synopsis

+
+
 namespace boost {
 
 template<class T, class U>
@@ -48,12 +49,12 @@ inline T* reinterpret_pointer_cast(U *ptr)
   
 } // namespace boost
 
-
-

As you can see from the above synopsis, the pointer cast functions are just - wrappers around standard C++ cast operators.

-

Example

-
-
+            
+

As you can see from the above synopsis, the pointer cast functions are just + wrappers around standard C++ cast operators.

+

Example

+
+
 #include <boost/pointer_cast.hpp>
 #include <boost/shared_ptr.hpp>
 
@@ -93,13 +94,13 @@ int main()
    delete ptr;
    return 0;
 }
-
-

The example demonstrates how the generic pointer casts help us create pointer - independent code.

-
-

Revised: $Date$

-

Copyright 2005 Ion Gaztañaga. Use, modification, and distribution are subject to - the Boost Software License, Version 1.0. (See accompanying file - LICENSE_1_0.txt or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)

- +
+

The example demonstrates how the generic pointer casts help us create pointer + independent code.

+
+

$Date$

+

Copyright 2005 Ion Gaztañaga. Use, modification, and distribution are subject to + the Boost Software License, Version 1.0. (See accompanying file + LICENSE_1_0.txt or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)

+ diff --git a/pointer_to_other.html b/pointer_to_other.html index e6b138c..e9be750 100644 --- a/pointer_to_other.html +++ b/pointer_to_other.html @@ -1,33 +1,33 @@ - - pointer_to_other.hpp - - - -

boost.png (6897 bytes)Header - boost/pointer_to_other.hpp

-

- The pointer to other utility provides a way, given a source pointer type, - to obtain a pointer of the same type to another pointee type. The utility is - defined in boost/pointer_to_other.hpp.

-

There is test/example code in pointer_to_other_test.cpp.

-

Contents

- -

Rationale

-

When building pointer independent classes, like memory managers, allocators, or - containers, there is often a need to define pointers generically, so that if a - template parameter represents a pointer (for example, a raw or smart pointer to - an int), we can define another pointer of the same type to another pointee (a - raw or smart pointer to a float.)

-
template <class IntPtr>
+    
+        pointer_to_other
+        
+    
+    
+        

boost.png (6897 bytes)pointer_to_other

+

+ The pointer to other utility provides a way, given a source pointer type, + to obtain a pointer of the same type to another pointee type. The utility is + defined in boost/pointer_to_other.hpp.

+

There is test/example code in pointer_to_other_test.cpp.

+

Contents

+ +

Rationale

+

When building pointer independent classes, like memory managers, allocators, or + containers, there is often a need to define pointers generically, so that if a + template parameter represents a pointer (for example, a raw or smart pointer to + an int), we can define another pointer of the same type to another pointee (a + raw or smart pointer to a float.)

+
template <class IntPtr>
 class FloatPointerHolder
 {   
    // Let's define a pointer to a float
@@ -35,8 +35,8 @@ class FloatPointerHolder
       <IntPtr, float>::type float_ptr_t;
    float_ptr_t float_ptr;
 };
-

Synopsis

-
+        

Synopsis

+
 namespace boost {
 
 template<class T, class U>
@@ -69,10 +69,10 @@ struct pointer_to_other< T*, U >
 };
 
 } // namespace boost
-

If these definitions are not correct for a specific smart pointer, we can define - a specialization of pointer_to_other.

-

Example

-
// Let's define a memory allocator that can
+        

If these definitions are not correct for a specific smart pointer, we can define + a specialization of pointer_to_other.

+

Example

+
// Let's define a memory allocator that can
 // work with raw and smart pointers
 
 #include <boost/pointer_to_other.hpp>
@@ -97,12 +97,12 @@ class memory_allocator
 
    block_ptr_t free_blocks;
 };
-

As we can see, using pointer_to_other we can create pointer independent code.

-
-

Last revised: $Date$

-

Copyright 2005, 2006 Ion Gaztañaga and Peter Dimov. Use, modification, - and distribution are subject to the Boost Software License, Version 1.0.
- (See accompanying file LICENSE_1_0.txt or a - copy at < http://www.boost.org/LICENSE_1_0.txt>.)

- +

As we can see, using pointer_to_other we can create pointer independent code.

+
+

$Date$

+

Copyright 2005, 2006 Ion Gaztañaga and Peter Dimov. Use, modification, + and distribution are subject to the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or a + copy at < http://www.boost.org/LICENSE_1_0.txt>.)

+ diff --git a/scoped_array.htm b/scoped_array.htm index 2d03509..3624e5d 100644 --- a/scoped_array.htm +++ b/scoped_array.htm @@ -1,38 +1,38 @@ - + - - scoped_array - - - -

boost.png (6897 bytes)scoped_array class template

-

The scoped_array class template stores a pointer to a dynamically - allocated array. (Dynamically allocated arrays are allocated with the C++ new[] - expression.) The array pointed to is guaranteed to be deleted, either on - destruction of the scoped_array, or via an explicit reset.

-

The scoped_array template is a simple solution for simple needs. It - supplies a basic "resource acquisition is initialization" facility, without - shared-ownership or transfer-of-ownership semantics. Both its name and - enforcement of semantics (by being - noncopyable) signal its intent to retain ownership solely within the - current scope. Because it is noncopyable, - it is safer than shared_array for pointers which should not be copied.

-

Because scoped_array is so simple, in its usual implementation every - operation is as fast as a built-in array pointer and it has no more space - overhead that a built-in array pointer.

-

It cannot be used in C++ standard library containers. See - shared_array if scoped_array does not meet your needs.

-

It cannot correctly hold a pointer to a single object. See scoped_ptr - for that usage.

-

A std::vector is an alternative to a scoped_array that is a bit - heavier duty but far more flexible. A boost::array is an alternative - that does not use dynamic allocation.

-

The class template is parameterized on T, the type of the object pointed - to. T must meet the smart pointer - common requirements.

-

Synopsis

-
namespace boost {
+    
+        scoped_array
+        
+    
+        
+        

boost.png (6897 bytes)scoped_array class template

+

The scoped_array class template stores a pointer to a dynamically + allocated array. (Dynamically allocated arrays are allocated with the C++ new[] + expression.) The array pointed to is guaranteed to be deleted, either on + destruction of the scoped_array, or via an explicit reset.

+

The scoped_array template is a simple solution for simple needs. It + supplies a basic "resource acquisition is initialization" facility, without + shared-ownership or transfer-of-ownership semantics. Both its name and + enforcement of semantics (by being + noncopyable) signal its intent to retain ownership solely within the + current scope. Because it is noncopyable, + it is safer than shared_array for pointers which should not be copied.

+

Because scoped_array is so simple, in its usual implementation every + operation is as fast as a built-in array pointer and it has no more space + overhead that a built-in array pointer.

+

It cannot be used in C++ standard library containers. See + shared_array if scoped_array does not meet your needs.

+

It cannot correctly hold a pointer to a single object. See scoped_ptr + for that usage.

+

A std::vector is an alternative to a scoped_array that is a bit + heavier duty but far more flexible. A boost::array is an alternative + that does not use dynamic allocation.

+

The class template is parameterized on T, the type of the object pointed + to. T must meet the smart pointer + common requirements.

+

Synopsis

+
namespace boost {
 
   template<class T> class scoped_array : noncopyable {
 
@@ -55,62 +55,61 @@
   template<class T> void swap(scoped_array<T> & a, scoped_array<T> & b); // never throws
 
 }
-

Members

-

- element_type

-
typedef T element_type;
-

Provides the type of the stored pointer.

-

constructors

-
explicit scoped_array(T * p = 0); // never throws
-

Constructs a scoped_array, storing a copy of p, which must have - been allocated via a C++ new[] expression or be 0. T is not - required be a complete type. See the smart pointer - common requirements.

-

destructor

-
~scoped_array(); // never throws
-

Deletes the array pointed to by the stored pointer. Note that delete[] on - a pointer with a value of 0 is harmless. The guarantee that this does not throw - exceptions depends on the requirement that the deleted array's objects' - destructors do not throw exceptions. See the smart pointer - common requirements.

-

reset

-
void reset(T * p = 0); // never throws
-

- Deletes the array pointed to by the stored pointer and then stores a copy of p, - which must have been allocated via a C++ new[] expression or be 0. The - guarantee that this does not throw exceptions depends on the requirement that - the deleted array's objects' destructors do not throw exceptions. See the smart - pointer common requirements.

-

subscripting

-
T & operator[](std::ptrdiff_t i) const; // never throws
-

Returns a reference to element i of the array pointed to by the stored - pointer. Behavior is undefined and almost certainly undesirable if the stored - pointer is 0, or if i is less than 0 or is greater than or equal to the - number of elements in the array.

-

get

-
T * get() const; // never throws
-

Returns the stored pointer. T need not be a complete type. See the smart - pointer common requirements.

-

conversions

-
operator unspecified-bool-type () const; // never throws
-

Returns an unspecified value that, when used in boolean contexts, is equivalent - to get() != 0.

-

swap

-
void swap(scoped_array & b); // never throws
-

Exchanges the contents of the two smart pointers. T need not be a - complete type. See the smart pointer common - requirements.

-

Free Functions

-

swap

-
template<class T> void swap(scoped_array<T> & a, scoped_array<T> & b); // never throws
-

Equivalent to a.swap(b). Matches the interface of std::swap. - Provided as an aid to generic programming.

-
-

Revised - 09 January 2003

-

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. - Copyright 2002-2005 Peter Dimov. 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.

- +

Members

+

+ element_type

+
typedef T element_type;
+

Provides the type of the stored pointer.

+

constructors

+
explicit scoped_array(T * p = 0); // never throws
+

Constructs a scoped_array, storing a copy of p, which must have + been allocated via a C++ new[] expression or be 0. T is not + required be a complete type. See the smart pointer + common requirements.

+

destructor

+
~scoped_array(); // never throws
+

Deletes the array pointed to by the stored pointer. Note that delete[] on + a pointer with a value of 0 is harmless. The guarantee that this does not throw + exceptions depends on the requirement that the deleted array's objects' + destructors do not throw exceptions. See the smart pointer + common requirements.

+

reset

+
void reset(T * p = 0); // never throws
+

+ Deletes the array pointed to by the stored pointer and then stores a copy of p, + which must have been allocated via a C++ new[] expression or be 0. The + guarantee that this does not throw exceptions depends on the requirement that + the deleted array's objects' destructors do not throw exceptions. See the smart + pointer common requirements.

+

subscripting

+
T & operator[](std::ptrdiff_t i) const; // never throws
+

Returns a reference to element i of the array pointed to by the stored + pointer. Behavior is undefined and almost certainly undesirable if the stored + pointer is 0, or if i is less than 0 or is greater than or equal to the + number of elements in the array.

+

get

+
T * get() const; // never throws
+

Returns the stored pointer. T need not be a complete type. See the smart + pointer common requirements.

+

conversions

+
operator unspecified-bool-type () const; // never throws
+

Returns an unspecified value that, when used in boolean contexts, is equivalent + to get() != 0.

+

swap

+
void swap(scoped_array & b); // never throws
+

Exchanges the contents of the two smart pointers. T need not be a + complete type. See the smart pointer common + requirements.

+

Free Functions

+

swap

+
template<class T> void swap(scoped_array<T> & a, scoped_array<T> & b); // never throws
+

Equivalent to a.swap(b). Matches the interface of std::swap. + Provided as an aid to generic programming.

+
+

$Date$

+

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. + Copyright 2002-2005 Peter Dimov. 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.

+ diff --git a/scoped_ptr.htm b/scoped_ptr.htm index fc5785c..1dbfbce 100644 --- a/scoped_ptr.htm +++ b/scoped_ptr.htm @@ -1,38 +1,38 @@ - + - - scoped_ptr - - - -

boost.png (6897 bytes)scoped_ptr class template

-

The scoped_ptr class template stores a pointer to a dynamically allocated - object. (Dynamically allocated objects are allocated with the C++ new expression.) - The object pointed to is guaranteed to be deleted, either on destruction of the scoped_ptr, - or via an explicit reset. See the example.

-

The scoped_ptr template is a simple solution for simple needs. It - supplies a basic "resource acquisition is initialization" facility, without - shared-ownership or transfer-of-ownership semantics. Both its name and - enforcement of semantics (by being - noncopyable) signal its intent to retain ownership solely within the - current scope. Because it is noncopyable, - it is safer than shared_ptr or std::auto_ptr for pointers which - should not be copied.

-

Because scoped_ptr is simple, in its usual implementation every operation - is as fast as for a built-in pointer and it has no more space overhead that a - built-in pointer.

-

scoped_ptr cannot be used in C++ Standard Library containers. - Use shared_ptr if you need a smart pointer - that can.

-

scoped_ptr cannot correctly hold a pointer to a dynamically - allocated array. See scoped_array for - that usage.

-

The class template is parameterized on T, the type of the object pointed - to. T must meet the smart pointer - common requirements.

-

Synopsis

-
namespace boost {
+    
+        scoped_ptr
+        
+    
+        
+        

boost.png (6897 bytes)scoped_ptr class template

+

The scoped_ptr class template stores a pointer to a dynamically allocated + object. (Dynamically allocated objects are allocated with the C++ new expression.) + The object pointed to is guaranteed to be deleted, either on destruction of the scoped_ptr, + or via an explicit reset. See the example.

+

The scoped_ptr template is a simple solution for simple needs. It + supplies a basic "resource acquisition is initialization" facility, without + shared-ownership or transfer-of-ownership semantics. Both its name and + enforcement of semantics (by being + noncopyable) signal its intent to retain ownership solely within the + current scope. Because it is noncopyable, + it is safer than shared_ptr or std::auto_ptr for pointers which + should not be copied.

+

Because scoped_ptr is simple, in its usual implementation every operation + is as fast as for a built-in pointer and it has no more space overhead that a + built-in pointer.

+

scoped_ptr cannot be used in C++ Standard Library containers. + Use shared_ptr if you need a smart pointer + that can.

+

scoped_ptr cannot correctly hold a pointer to a dynamically + allocated array. See scoped_array for + that usage.

+

The class template is parameterized on T, the type of the object pointed + to. T must meet the smart pointer + common requirements.

+

Synopsis

+
namespace boost {
 
   template<class T> class scoped_ptr : noncopyable {
 
@@ -56,60 +56,60 @@
   template<class T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b); // never throws
 
 }
-

Members

-

element_type

-
typedef T element_type;
-

Provides the type of the stored pointer.

-

constructors

-
explicit scoped_ptr(T * p = 0); // never throws
-

Constructs a scoped_ptr, storing a copy of p, which must have been - allocated via a C++ new expression or be 0. T is not required be - a complete type. See the smart pointer common - requirements.

-

destructor

-
~scoped_ptr(); // never throws
-

Destroys the object pointed to by the stored pointer, if any, as if by using delete - this->get().

-

- The guarantee that this does not throw exceptions depends on the requirement - that the deleted object's destructor does not throw exceptions. See the smart - pointer common requirements.

-

reset

-
void reset(T * p = 0); // never throws
-

- Deletes the object pointed to by the stored pointer and then stores a copy of - p, which must have been allocated via a C++ new expression or be 0. The - guarantee that this does not throw exceptions depends on the requirement that - the deleted object's destructor does not throw exceptions. See the smart - pointer common requirements.

-

indirection

-
T & operator*() const; // never throws
-

Returns a reference to the object pointed to by the stored pointer. Behavior is - undefined if the stored pointer is 0.

-
T * operator->() const; // never throws
-

Returns the stored pointer. Behavior is undefined if the stored pointer is 0.

-

get

-
T * get() const; // never throws
-

Returns the stored pointer. T need not be a complete type. See the smart - pointer common requirements.

-

conversions

-
operator unspecified-bool-type () const; // never throws
-

Returns an unspecified value that, when used in boolean contexts, is equivalent - to get() != 0.

-

swap

-
void swap(scoped_ptr & b); // never throws
-

Exchanges the contents of the two smart pointers. T need not be a - complete type. See the smart pointer common - requirements.

-

Free Functions

-

swap

-
template<class T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b); // never throws
-

Equivalent to a.swap(b). Matches the interface of std::swap. - Provided as an aid to generic programming.

-

Example

-

Here's an example that uses scoped_ptr.

-
-
#include <boost/scoped_ptr.hpp>
+        

Members

+

element_type

+
typedef T element_type;
+

Provides the type of the stored pointer.

+

constructors

+
explicit scoped_ptr(T * p = 0); // never throws
+

Constructs a scoped_ptr, storing a copy of p, which must have been + allocated via a C++ new expression or be 0. T is not required be + a complete type. See the smart pointer common + requirements.

+

destructor

+
~scoped_ptr(); // never throws
+

Destroys the object pointed to by the stored pointer, if any, as if by using delete + this->get().

+

+ The guarantee that this does not throw exceptions depends on the requirement + that the deleted object's destructor does not throw exceptions. See the smart + pointer common requirements.

+

reset

+
void reset(T * p = 0); // never throws
+

+ Deletes the object pointed to by the stored pointer and then stores a copy of + p, which must have been allocated via a C++ new expression or be 0. The + guarantee that this does not throw exceptions depends on the requirement that + the deleted object's destructor does not throw exceptions. See the smart + pointer common requirements.

+

indirection

+
T & operator*() const; // never throws
+

Returns a reference to the object pointed to by the stored pointer. Behavior is + undefined if the stored pointer is 0.

+
T * operator->() const; // never throws
+

Returns the stored pointer. Behavior is undefined if the stored pointer is 0.

+

get

+
T * get() const; // never throws
+

Returns the stored pointer. T need not be a complete type. See the smart + pointer common requirements.

+

conversions

+
operator unspecified-bool-type () const; // never throws
+

Returns an unspecified value that, when used in boolean contexts, is equivalent + to get() != 0.

+

swap

+
void swap(scoped_ptr & b); // never throws
+

Exchanges the contents of the two smart pointers. T need not be a + complete type. See the smart pointer common + requirements.

+

Free Functions

+

swap

+
template<class T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b); // never throws
+

Equivalent to a.swap(b). Matches the interface of std::swap. + Provided as an aid to generic programming.

+

Example

+

Here's an example that uses scoped_ptr.

+
+
#include <boost/scoped_ptr.hpp>
 #include <iostream>
 
 struct Shoe { ~Shoe() { std::cout << "Buckle my shoe\n"; } };
@@ -128,54 +128,53 @@ int main()
     std::cout << my_instance.add_one() << '\n';
     std::cout << my_instance.add_one() << '\n';
 }
-
-

The example program produces the beginning of a child's nursery rhyme:

-
-
1
+        
+

The example program produces the beginning of a child's nursery rhyme:

+
+
1
 2
 Buckle my shoe
-
-

Rationale

-

The primary reason to use scoped_ptr rather than auto_ptr is to - let readers of your code know that you intend "resource acquisition is - initialization" to be applied only for the current scope, and have no intent to - transfer ownership.

-

A secondary reason to use scoped_ptr is to prevent a later maintenance - programmer from adding a function that transfers ownership by returning the auto_ptr, - because the maintenance programmer saw auto_ptr, and assumed ownership - could safely be transferred.

-

Think of bool vs int. We all know that under the covers bool - is usually just an int. Indeed, some argued against including bool - in the C++ standard because of that. But by coding bool rather than int, - you tell your readers what your intent is. Same with scoped_ptr; by - using it you are signaling intent.

-

It has been suggested that scoped_ptr<T> is equivalent to std::auto_ptr<T> - const. Ed Brey pointed out, however, that reset will not work on - a std::auto_ptr<T> const.

-

Handle/Body Idiom

-

One common usage of scoped_ptr is to implement a handle/body (also called - pimpl) idiom which avoids exposing the body (implementation) in the header - file.

-

The scoped_ptr_example_test.cpp - sample program includes a header file, scoped_ptr_example.hpp, - which uses a scoped_ptr<> to an incomplete type to hide the - implementation. The instantiation of member functions which require a complete - type occurs in the scoped_ptr_example.cpp - implementation file.

-

Frequently Asked Questions

-

Q. Why doesn't scoped_ptr have a release() member?
- A. When reading source code, it is valuable to be able to draw - conclusions about program behavior based on the types being used. If scoped_ptr - had a release() member, it would become possible to transfer ownership of the - held pointer, weakening its role as a way of limiting resource lifetime to a - given context. Use std::auto_ptr where transfer of ownership - is required. (supplied by Dave Abrahams)

-
-

Revised - 09 January 2003

-

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. - Copyright 2002-2005 Peter Dimov. 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.

- +
+

Rationale

+

The primary reason to use scoped_ptr rather than auto_ptr is to + let readers of your code know that you intend "resource acquisition is + initialization" to be applied only for the current scope, and have no intent to + transfer ownership.

+

A secondary reason to use scoped_ptr is to prevent a later maintenance + programmer from adding a function that transfers ownership by returning the auto_ptr, + because the maintenance programmer saw auto_ptr, and assumed ownership + could safely be transferred.

+

Think of bool vs int. We all know that under the covers bool + is usually just an int. Indeed, some argued against including bool + in the C++ standard because of that. But by coding bool rather than int, + you tell your readers what your intent is. Same with scoped_ptr; by + using it you are signaling intent.

+

It has been suggested that scoped_ptr<T> is equivalent to std::auto_ptr<T> + const. Ed Brey pointed out, however, that reset will not work on + a std::auto_ptr<T> const.

+

Handle/Body Idiom

+

One common usage of scoped_ptr is to implement a handle/body (also called + pimpl) idiom which avoids exposing the body (implementation) in the header + file.

+

The scoped_ptr_example_test.cpp + sample program includes a header file, scoped_ptr_example.hpp, + which uses a scoped_ptr<> to an incomplete type to hide the + implementation. The instantiation of member functions which require a complete + type occurs in the scoped_ptr_example.cpp + implementation file.

+

Frequently Asked Questions

+

Q. Why doesn't scoped_ptr have a release() member?
+ A. When reading source code, it is valuable to be able to draw + conclusions about program behavior based on the types being used. If scoped_ptr + had a release() member, it would become possible to transfer ownership of the + held pointer, weakening its role as a way of limiting resource lifetime to a + given context. Use std::auto_ptr where transfer of ownership + is required. (supplied by Dave Abrahams)

+
+

$Date

+

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. + Copyright 2002-2005 Peter Dimov. 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.

+ diff --git a/shared_array.htm b/shared_array.htm index 320a54a..4c31458 100644 --- a/shared_array.htm +++ b/shared_array.htm @@ -1,35 +1,35 @@ - + - - shared_array - - - -

boost.png (6897 bytes)shared_array class template

-

The shared_array class template stores a pointer to a dynamically - allocated array. (Dynamically allocated array are allocated with the C++ new[] - expression.) The object pointed to is guaranteed to be deleted when the last shared_array - pointing to it is destroyed or reset.

-

Every shared_array meets the CopyConstructible and Assignable - requirements of the C++ Standard Library, and so can be used in standard - library containers. Comparison operators are supplied so that shared_array - works with the standard library's associative containers.

-

Normally, a shared_array cannot correctly hold a pointer to an object - that has been allocated with the non-array form of new. See - shared_ptr for that usage.

-

Because the implementation uses reference counting, cycles of shared_array - instances will not be reclaimed. For example, if main() holds a shared_array - to A, which directly or indirectly holds a shared_array back to A, - A's use count will be 2. Destruction of the original shared_array - will leave A dangling with a use count of 1.

-

A shared_ptr to a std::vector is an alternative to a shared_array - that is a bit heavier duty but far more flexible.

-

The class template is parameterized on T, the type of the object pointed - to. T must meet the smart pointer - common requirements.

-

Synopsis

-
namespace boost {
+    
+        shared_array
+        
+    
+        
+        

boost.png (6897 bytes)shared_array class template

+

The shared_array class template stores a pointer to a dynamically + allocated array. (Dynamically allocated array are allocated with the C++ new[] + expression.) The object pointed to is guaranteed to be deleted when the last shared_array + pointing to it is destroyed or reset.

+

Every shared_array meets the CopyConstructible and Assignable + requirements of the C++ Standard Library, and so can be used in standard + library containers. Comparison operators are supplied so that shared_array + works with the standard library's associative containers.

+

Normally, a shared_array cannot correctly hold a pointer to an object + that has been allocated with the non-array form of new. See + shared_ptr for that usage.

+

Because the implementation uses reference counting, cycles of shared_array + instances will not be reclaimed. For example, if main() holds a shared_array + to A, which directly or indirectly holds a shared_array back to A, + A's use count will be 2. Destruction of the original shared_array + will leave A dangling with a use count of 1.

+

A shared_ptr to a std::vector is an alternative to a shared_array + that is a bit heavier duty but far more flexible.

+

The class template is parameterized on T, the type of the object pointed + to. T must meet the smart pointer + common requirements.

+

Synopsis

+
namespace boost {
 
   template<class T> class shared_array {
 
@@ -68,118 +68,116 @@
   template<class T> void swap(shared_array<T> & a, shared_array<T> & b); // never throws
 
 }
-

Members

-

element_type

-
typedef T element_type;
-

Provides the type of the stored pointer.

-

constructors

-
explicit shared_array(T * p = 0);
-

Constructs a shared_array, storing a copy of p, which must be a - pointer to an array that was allocated via a C++ new[] expression or be - 0. Afterwards, the use count is 1 (even if p == 0; see - ~shared_array). The only exception which may be thrown by this - constructor is std::bad_alloc. If an exception is thrown, delete[] p - is called.

-
template<class D> shared_array(T * p, D d);
-

Constructs a shared_array, storing a copy of p and of d. - Afterwards, the use count is 1. D's copy - constructor and destructor must not throw. When the the time comes to delete - the array pointed to by p, the object d is used in the statement d(p). - Invoking the object d with parameter p in this way must not - throw. The only exception which may be thrown by this constructor is std::bad_alloc. - If an exception is thrown, d(p) is called.

-
shared_array(shared_array const & r); // never throws
-

Constructs a shared_array, as if by storing a copy of the pointer stored - in r. Afterwards, the use count for all copies - is 1 more than the initial use count.

-

destructor

-
~shared_array(); // never throws
-

Decrements the use count. Then, if the use count is 0, - deletes the array pointed to by the stored pointer. Note that delete[] on - a pointer with a value of 0 is harmless. T need not be a complete type. - The guarantee that this does not throw exceptions depends on the requirement - that the deleted object's destructor does not throw exceptions. See the smart - pointer common requirements.

-

assignment

-
shared_array & operator=(shared_array const & r); // never throws
-

Constructs a new shared_array as described above, - then replaces this shared_array with the new one, destroying the - replaced object.

-

reset

-
void reset(T * p = 0);
-

Constructs a new shared_array as described above, - then replaces this shared_array with the new one, destroying the - replaced object. The only exception which may be thrown is std::bad_alloc. - If an exception is thrown, delete[] p is called.

-
template<class D> void reset(T * p, D d);
-

Constructs a new shared_array as described above, - then replaces this shared_array with the new one, destroying the - replaced object. D's copy constructor must not throw. The only exception - which may be thrown is std::bad_alloc. If an exception is thrown, d(p) - is called.

-

indexing

-
T & operator[](std::ptrdiff_t i) const; // never throws
-

Returns a reference to element i of the array pointed to by the stored - pointer. Behavior is undefined and almost certainly undesirable if the stored - pointer is 0, or if i is less than 0 or is greater than or equal to the - number of elements in the array.

-

get

-
T * get() const; // never throws
-

Returns the stored pointer. T need not be a complete type. See the smart - pointer common requirements.

-

unique

-
bool unique() const; // never throws
-

Returns true if no other shared_array is sharing ownership of the stored - pointer, false otherwise. T need not be a complete type. See the smart - pointer common requirements.

-

use_count

-
long use_count() const; // never throws
-

Returns the number of shared_array objects sharing ownership of the - stored pointer. T need not be a complete type. See the smart pointer - common requirements.

-

Because use_count is not necessarily efficient to implement for - implementations of shared_array that do not use an explicit reference - count, it might be removed from some future version. Thus it should be used for - debugging purposes only, and not production code.

-

conversions

-
operator unspecified-bool-type () const; // never throws
-

Returns an unspecified value that, when used in boolean contexts, is equivalent - to get() != 0.

-

swap

-
void swap(shared_ptr & b); // never throws
-

Exchanges the contents of the two smart pointers. T need not be a - complete type. See the smart pointer common - requirements.

-

Free Functions

-

comparison

-
template<class T>
+        

Members

+

element_type

+
typedef T element_type;
+

Provides the type of the stored pointer.

+

constructors

+
explicit shared_array(T * p = 0);
+

Constructs a shared_array, storing a copy of p, which must be a + pointer to an array that was allocated via a C++ new[] expression or be + 0. Afterwards, the use count is 1 (even if p == 0; see + ~shared_array). The only exception which may be thrown by this + constructor is std::bad_alloc. If an exception is thrown, delete[] p + is called.

+
template<class D> shared_array(T * p, D d);
+

Constructs a shared_array, storing a copy of p and of d. + Afterwards, the use count is 1. D's copy + constructor and destructor must not throw. When the the time comes to delete + the array pointed to by p, the object d is used in the statement d(p). + Invoking the object d with parameter p in this way must not + throw. The only exception which may be thrown by this constructor is std::bad_alloc. + If an exception is thrown, d(p) is called.

+
shared_array(shared_array const & r); // never throws
+

Constructs a shared_array, as if by storing a copy of the pointer stored + in r. Afterwards, the use count for all copies + is 1 more than the initial use count.

+

destructor

+
~shared_array(); // never throws
+

Decrements the use count. Then, if the use count is 0, + deletes the array pointed to by the stored pointer. Note that delete[] on + a pointer with a value of 0 is harmless. T need not be a complete type. + The guarantee that this does not throw exceptions depends on the requirement + that the deleted object's destructor does not throw exceptions. See the smart + pointer common requirements.

+

assignment

+
shared_array & operator=(shared_array const & r); // never throws
+

Constructs a new shared_array as described above, + then replaces this shared_array with the new one, destroying the + replaced object.

+

reset

+
void reset(T * p = 0);
+

Constructs a new shared_array as described above, + then replaces this shared_array with the new one, destroying the + replaced object. The only exception which may be thrown is std::bad_alloc. + If an exception is thrown, delete[] p is called.

+
template<class D> void reset(T * p, D d);
+

Constructs a new shared_array as described above, + then replaces this shared_array with the new one, destroying the + replaced object. D's copy constructor must not throw. The only exception + which may be thrown is std::bad_alloc. If an exception is thrown, d(p) + is called.

+

indexing

+
T & operator[](std::ptrdiff_t i) const; // never throws
+

Returns a reference to element i of the array pointed to by the stored + pointer. Behavior is undefined and almost certainly undesirable if the stored + pointer is 0, or if i is less than 0 or is greater than or equal to the + number of elements in the array.

+

get

+
T * get() const; // never throws
+

Returns the stored pointer. T need not be a complete type. See the smart + pointer common requirements.

+

unique

+
bool unique() const; // never throws
+

Returns true if no other shared_array is sharing ownership of the stored + pointer, false otherwise. T need not be a complete type. See the smart + pointer common requirements.

+

use_count

+
long use_count() const; // never throws
+

Returns the number of shared_array objects sharing ownership of the + stored pointer. T need not be a complete type. See the smart pointer + common requirements.

+

Because use_count is not necessarily efficient to implement for + implementations of shared_array that do not use an explicit reference + count, it might be removed from some future version. Thus it should be used for + debugging purposes only, and not production code.

+

conversions

+
operator unspecified-bool-type () const; // never throws
+

Returns an unspecified value that, when used in boolean contexts, is equivalent + to get() != 0.

+

swap

+
void swap(shared_ptr & b); // never throws
+

Exchanges the contents of the two smart pointers. T need not be a + complete type. See the smart pointer common + requirements.

+

Free Functions

+

comparison

+
template<class T>
   bool operator==(shared_array<T> const & a, shared_array<T> const & b); // never throws
 template<class T>
   bool operator!=(shared_array<T> const & a, shared_array<T> const & b); // never throws
 template<class T>
   bool operator<(shared_array<T> const & a, shared_array<T> const & b); // never throws
-

Compares the stored pointers of the two smart pointers. T need not be a - complete type. See the smart pointer common - requirements.

-

The operator< overload is provided to define an ordering so that shared_array - objects can be used in associative containers such as std::map. The - implementation uses std::less<T *> to perform the comparison. This - ensures that the comparison is handled correctly, since the standard mandates - that relational operations on pointers are unspecified (5.9 [expr.rel] - paragraph 2) but std::less<> on pointers is well-defined (20.3.3 - [lib.comparisons] paragraph 8).

-

swap

-
template<class T>
+        

Compares the stored pointers of the two smart pointers. T need not be a + complete type. See the smart pointer common + requirements.

+

The operator< overload is provided to define an ordering so that shared_array + objects can be used in associative containers such as std::map. The + implementation uses std::less<T *> to perform the comparison. This + ensures that the comparison is handled correctly, since the standard mandates + that relational operations on pointers are unspecified (5.9 [expr.rel] + paragraph 2) but std::less<> on pointers is well-defined (20.3.3 + [lib.comparisons] paragraph 8).

+

swap

+
template<class T>
   void swap(shared_array<T> & a, shared_array<T> & b) // never throws
-

Equivalent to a.swap(b). Matches the interface of std::swap. - Provided as an aid to generic programming.

-
-

Revised - - 09 January 2003

-

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. - Copyright 2002-2005 Peter Dimov. 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.

- +

Equivalent to a.swap(b). Matches the interface of std::swap. + Provided as an aid to generic programming.

+
+

$Date

+

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. + Copyright 2002-2005 Peter Dimov. 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.

+ diff --git a/shared_ptr.htm b/shared_ptr.htm index 0043200..d58e1f5 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -1,85 +1,86 @@ - + - - shared_ptr - - - -

boost::shared_ptr class template

-

Introduction
- Best Practices
- Synopsis
- Members
- Free Functions
- Example
- Handle/Body Idiom
- Thread Safety
- Frequently Asked Questions
- Smart Pointer Timings
- Programming Techniques

-

Introduction

-

The shared_ptr class template stores a pointer to a dynamically allocated - object, typically with a C++ new-expression. The object pointed to is - guaranteed to be deleted when the last shared_ptr pointing to it is - destroyed or reset.

-
Example:
shared_ptr<X> p1( new X );
+    
+        shared_ptr
+        
+    
+    
+        

boost.png (6897 bytes)shared_ptr class template

+

Introduction
+ Best Practices
+ Synopsis
+ Members
+ Free Functions
+ Example
+ Handle/Body Idiom
+ Thread Safety
+ Frequently Asked Questions
+ Smart Pointer Timings
+ Programming Techniques

+

Introduction

+

The shared_ptr class template stores a pointer to a dynamically allocated + object, typically with a C++ new-expression. The object pointed to is + guaranteed to be deleted when the last shared_ptr pointing to it is + destroyed or reset.

+
Example:
shared_ptr<X> p1( new X );
 shared_ptr<void> p2( new int(5) );
 
-

shared_ptr deletes the exact pointer that has been passed at construction time, - complete with its original type, regardless of the template parameter. In the second example above, - when p2 is destroyed or reset, it will call delete on the original int* - that has been passed to the constructor, even though p2 itself is of type - shared_ptr<void> and stores a pointer of type void*.

+

shared_ptr deletes the exact pointer that has been passed at construction time, + complete with its original type, regardless of the template parameter. In the second example above, + when p2 is destroyed or reset, it will call delete on the original int* + that has been passed to the constructor, even though p2 itself is of type + shared_ptr<void> and stores a pointer of type void*.

-

Every shared_ptr meets the CopyConstructible, MoveConstructible, - CopyAssignable and MoveAssignable - requirements of the C++ Standard Library, and can be used in standard - library containers. Comparison operators are supplied so that shared_ptr - works with the standard library's associative containers.

-

Because the implementation uses reference counting, cycles of shared_ptr instances - will not be reclaimed. For example, if main() holds a shared_ptr to - A, which directly or indirectly holds a shared_ptr back to A, - A's use count will be 2. Destruction of the original shared_ptr will - leave A dangling with a use count of 1. Use weak_ptr - to "break cycles."

-

The class template is parameterized on T, the type of the object pointed - to. shared_ptr and most of its member functions place no - requirements on T; it is allowed to be an incomplete type, or - void. Member functions that do place additional requirements - (constructors, reset) are explicitly - documented below.

-

shared_ptr<T> can be implicitly converted to shared_ptr<U> - whenever T* can be implicitly converted to U*. - In particular, shared_ptr<T> is implicitly convertible - to shared_ptr<T const>, to shared_ptr<U> - where U is an accessible base of T, and to - shared_ptr<void>.

-

shared_ptr is now part of the C++11 Standard, as std::shared_ptr.

-

Starting with Boost release 1.53, shared_ptr can be used to hold a pointer to a dynamically - allocated array. This is accomplished by using an array type (T[] or T[N]) as - the template parameter. There is almost no difference between using an unsized array, T[], - and a sized array, T[N]; the latter just enables operator[] to perform a range check - on the index.

-
Example:
shared_ptr<double[1024]> p1( new double[1024] );
+        

Every shared_ptr meets the CopyConstructible, MoveConstructible, + CopyAssignable and MoveAssignable + requirements of the C++ Standard Library, and can be used in standard + library containers. Comparison operators are supplied so that shared_ptr + works with the standard library's associative containers.

+

Because the implementation uses reference counting, cycles of shared_ptr instances + will not be reclaimed. For example, if main() holds a shared_ptr to + A, which directly or indirectly holds a shared_ptr back to A, + A's use count will be 2. Destruction of the original shared_ptr will + leave A dangling with a use count of 1. Use weak_ptr + to "break cycles."

+

The class template is parameterized on T, the type of the object pointed + to. shared_ptr and most of its member functions place no + requirements on T; it is allowed to be an incomplete type, or + void. Member functions that do place additional requirements + (constructors, reset) are explicitly + documented below.

+

shared_ptr<T> can be implicitly converted to shared_ptr<U> + whenever T* can be implicitly converted to U*. + In particular, shared_ptr<T> is implicitly convertible + to shared_ptr<T const>, to shared_ptr<U> + where U is an accessible base of T, and to + shared_ptr<void>.

+

shared_ptr is now part of the C++11 Standard, as std::shared_ptr.

+

Starting with Boost release 1.53, shared_ptr can be used to hold a pointer to a dynamically + allocated array. This is accomplished by using an array type (T[] or T[N]) as + the template parameter. There is almost no difference between using an unsized array, T[], + and a sized array, T[N]; the latter just enables operator[] to perform a range check + on the index.

+
Example:
shared_ptr<double[1024]> p1( new double[1024] );
 shared_ptr<double[]> p2( new double[n] );
 
-

Best Practices

-

A simple guideline that nearly eliminates the possibility of memory leaks is: - always use a named smart pointer variable to hold the result of new. - Every occurence of the new keyword in the code should have the - form:

-
shared_ptr<T> p(new Y);
-

It is, of course, acceptable to use another smart pointer in place of shared_ptr - above; having T and Y be the same type, or - passing arguments to Y's constructor is also OK.

-

If you observe this guideline, it naturally follows that you will have no - explicit delete statements; try/catch constructs will - be rare.

-

Avoid using unnamed shared_ptr temporaries to save typing; to - see why this is dangerous, consider this example:

-
void f(shared_ptr<int>, int);
+        

Best Practices

+

A simple guideline that nearly eliminates the possibility of memory leaks is: + always use a named smart pointer variable to hold the result of new. + Every occurence of the new keyword in the code should have the + form:

+
shared_ptr<T> p(new Y);
+

It is, of course, acceptable to use another smart pointer in place of shared_ptr + above; having T and Y be the same type, or + passing arguments to Y's constructor is also OK.

+

If you observe this guideline, it naturally follows that you will have no + explicit delete statements; try/catch constructs will + be rare.

+

Avoid using unnamed shared_ptr temporaries to save typing; to + see why this is dangerous, consider this example:

+
void f(shared_ptr<int>, int);
 int g();
 
 void ok()
@@ -93,21 +94,21 @@ void bad()
     f( shared_ptr<int>( new int(2) ), g() );
 }
 
-

The function ok follows the guideline to the letter, whereas - bad constructs the temporary shared_ptr in place, - admitting the possibility of a memory leak. Since function arguments are - evaluated in unspecified order, it is possible for new int(2) to - be evaluated first, g() second, and we may never get to the +

The function ok follows the guideline to the letter, whereas + bad constructs the temporary shared_ptr in place, + admitting the possibility of a memory leak. Since function arguments are + evaluated in unspecified order, it is possible for new int(2) to + be evaluated first, g() second, and we may never get to the shared_ptrconstructor if g throws an exception. - See Herb Sutter's treatment (also - here) of the issue for more information.

-

The exception safety problem described above may also be eliminated by using - the make_shared - or allocate_shared - factory functions defined in boost/make_shared.hpp. - These factory functions also provide an efficiency benefit by consolidating allocations.

-

Synopsis

-
namespace boost {
+            See Herb Sutter's treatment (also 
+            here) of the issue for more information.

+

The exception safety problem described above may also be eliminated by using + the make_shared + or allocate_shared + factory functions defined in boost/make_shared.hpp. + These factory functions also provide an efficiency benefit by consolidating allocations.

+

Synopsis

+
namespace boost {
 
   class bad_weak_ptr: public std::exception;
 
@@ -227,479 +228,479 @@ void bad()
   template<class D, class T>
     D * get_deleter(shared_ptr<T> const & p);
 }
-

Members

-

element_type

-
typedef ... element_type;
-
-

element_type is T when T is not an array type, +

Members

+

element_type

+
typedef ... element_type;
+
+

element_type is T when T is not an array type, and U when T is U[] or U[N].

-
-

default constructor

-
shared_ptr(); // never throws
+        
+

default constructor

+
shared_ptr(); // never throws
 shared_ptr(std::nullptr_t); // never throws
-
-

Effects: Constructs an empty shared_ptr.

-

Postconditions: use_count() == 0 && get() == 0.

-

Throws: nothing.

-
-

[The nothrow guarantee is important, since reset() is specified - in terms of the default constructor; this implies that the constructor must not - allocate memory.]

-

pointer constructor

-
template<class Y> explicit shared_ptr(Y * p);
-
-

Requirements: - Y must be a complete type. - The expression delete[] p, when T is an array type, or delete p, - when T is not an array type, - must be well-formed, must not invoke undefined behavior, and must not throw exceptions. - When T is U[N], Y (*) [N] must be convertible to T*; - when T is U[], Y (*) [] must be convertible to T*; - otherwise, Y* must be convertible to T*. -

-

Effects: - When T is not an array type, constructs a shared_ptr that owns - the pointer p. - Otherwise, constructs a shared_ptr that owns - p and a deleter of an unspecified type that calls delete[] p.

+
+

Effects: Constructs an empty shared_ptr.

+

Postconditions: use_count() == 0 && get() == 0.

+

Throws: nothing.

+
+

[The nothrow guarantee is important, since reset() is specified + in terms of the default constructor; this implies that the constructor must not + allocate memory.]

+

pointer constructor

+
template<class Y> explicit shared_ptr(Y * p);
+
+

Requirements: + Y must be a complete type. + The expression delete[] p, when T is an array type, or delete p, + when T is not an array type, + must be well-formed, must not invoke undefined behavior, and must not throw exceptions. + When T is U[N], Y (*) [N] must be convertible to T*; + when T is U[], Y (*) [] must be convertible to T*; + otherwise, Y* must be convertible to T*. +

+

Effects: + When T is not an array type, constructs a shared_ptr that owns + the pointer p. + Otherwise, constructs a shared_ptr that owns + p and a deleter of an unspecified type that calls delete[] p.

Postconditions: use_count() == 1 && get() == p. If T is not an array type and p is unambiguously convertible to enable_shared_from_this<V>* for some V, p->shared_from_this() returns a copy of *this.

Throws: std::bad_alloc, or an implementation-defined - exception when a resource other than memory could not be obtained.

-

Exception safety: If an exception is thrown, the constructor calls - delete[] p, when T is an array type, - or delete p, when T is not an array type.

-

Notes: p must be a pointer to an object that was - allocated via a C++ new expression or be 0. The postcondition that - use count is 1 holds even if p is 0; invoking delete - on a pointer that has a value of 0 is harmless.

-
-

[This constructor is a template in order to remember the actual - pointer type passed. The destructor will call delete with the - same pointer, complete with its original type, even when T does - not have a virtual destructor, or is void.]

-

constructors taking a deleter

-
template<class Y, class D> shared_ptr(Y * p, D d);
+                exception when a resource other than memory could not be obtained.

+

Exception safety: If an exception is thrown, the constructor calls + delete[] p, when T is an array type, + or delete p, when T is not an array type.

+

Notes: p must be a pointer to an object that was + allocated via a C++ new expression or be 0. The postcondition that + use count is 1 holds even if p is 0; invoking delete + on a pointer that has a value of 0 is harmless.

+
+

[This constructor is a template in order to remember the actual + pointer type passed. The destructor will call delete with the + same pointer, complete with its original type, even when T does + not have a virtual destructor, or is void.]

+

constructors taking a deleter

+
template<class Y, class D> shared_ptr(Y * p, D d);
 template<class Y, class D, class A> shared_ptr(Y * p, D d, A a);
 template<class D> shared_ptr(std::nullptr_t p, D d);
 template<class D, class A> shared_ptr(std::nullptr_t p, D d, A a);
-
-

Requirements: - D must be CopyConstructible. The copy constructor and destructor - of D must not throw. The expression d(p) must be - well-formed, must not invoke undefined behavior, and must not throw exceptions. - A must be an Allocator, as described in section 20.1.5 - (Allocator requirements) of the C++ Standard. - When T is U[N], Y (*) [N] must be convertible to T*; - when T is U[], Y (*) [] must be convertible to T*; - otherwise, Y* must be convertible to T*. -

-

Effects: Constructs a shared_ptr that owns the pointer - p and the deleter d. The constructors taking an allocator a - allocate memory using a copy of a.

+
+

Requirements: + D must be CopyConstructible. The copy constructor and destructor + of D must not throw. The expression d(p) must be + well-formed, must not invoke undefined behavior, and must not throw exceptions. + A must be an Allocator, as described in section 20.1.5 + (Allocator requirements) of the C++ Standard. + When T is U[N], Y (*) [N] must be convertible to T*; + when T is U[], Y (*) [] must be convertible to T*; + otherwise, Y* must be convertible to T*. +

+

Effects: Constructs a shared_ptr that owns the pointer + p and the deleter d. The constructors taking an allocator a + allocate memory using a copy of a.

Postconditions: use_count() == 1 && get() == p. If T is not an array type and p is unambiguously convertible to enable_shared_from_this<V>* for some V, p->shared_from_this() returns a copy of *this.

-

Throws: std::bad_alloc, or an implementation-defined - exception when a resource other than memory could not be obtained.

-

Exception safety: If an exception is thrown, d(p) is called.

-

Notes: When the the time comes to delete the object pointed to by p, - the stored copy of d is invoked with the stored copy of p - as an argument.

-
-

[Custom deallocators allow a factory function returning a shared_ptr - to insulate the user from its memory allocation strategy. Since the deallocator - is not part of the type, changing the allocation strategy does not break source - or binary compatibility, and does not require a client recompilation. For - example, a "no-op" deallocator is useful when returning a shared_ptr - to a statically allocated object, and other variations allow a shared_ptr - to be used as a wrapper for another smart pointer, easing interoperability.

-

The support for custom deallocators does not impose significant overhead. Other - shared_ptr features still require a deallocator to be kept.

-

The requirement that the copy constructor of D does not throw comes from - the pass by value. If the copy constructor throws, the pointer would leak.]

-

copy and converting constructors

-
shared_ptr(shared_ptr const & r); // never throws
+            

Throws: std::bad_alloc, or an implementation-defined + exception when a resource other than memory could not be obtained.

+

Exception safety: If an exception is thrown, d(p) is called.

+

Notes: When the the time comes to delete the object pointed to by p, + the stored copy of d is invoked with the stored copy of p + as an argument.

+
+

[Custom deallocators allow a factory function returning a shared_ptr + to insulate the user from its memory allocation strategy. Since the deallocator + is not part of the type, changing the allocation strategy does not break source + or binary compatibility, and does not require a client recompilation. For + example, a "no-op" deallocator is useful when returning a shared_ptr + to a statically allocated object, and other variations allow a shared_ptr + to be used as a wrapper for another smart pointer, easing interoperability.

+

The support for custom deallocators does not impose significant overhead. Other + shared_ptr features still require a deallocator to be kept.

+

The requirement that the copy constructor of D does not throw comes from + the pass by value. If the copy constructor throws, the pointer would leak.]

+

copy and converting constructors

+
shared_ptr(shared_ptr const & r); // never throws
 template<class Y> shared_ptr(shared_ptr<Y> const & r); // never throws
-
-

Requires: Y* should be convertible to T*.

-

Effects: If r is empty, constructs an empty shared_ptr; - otherwise, constructs a shared_ptr that shares ownership with r.

-

Postconditions: get() == r.get() && use_count() == - r.use_count().

-

Throws: nothing.

-
-

move constructors

-
shared_ptr(shared_ptr && r); // never throws
+        
+

Requires: Y* should be convertible to T*.

+

Effects: If r is empty, constructs an empty shared_ptr; + otherwise, constructs a shared_ptr that shares ownership with r.

+

Postconditions: get() == r.get() && use_count() == + r.use_count().

+

Throws: nothing.

+
+

move constructors

+
shared_ptr(shared_ptr && r); // never throws
 template<class Y> shared_ptr(shared_ptr<Y> && r); // never throws
-
-

Requires: Y* should be convertible to T*.

-

Effects: Move-constructs a shared_ptr from r.

-

Postconditions: *this contains the old value of r. r is empty and r.get() == 0.

-

Throws: nothing.

-
-

aliasing constructor

-
template<class Y> shared_ptr(shared_ptr<Y> const & r, element_type * p); // never throws
-
-

Effects: constructs a shared_ptr that shares ownership with - r and stores p.

-

Postconditions: get() == p && use_count() == r.use_count().

-

Throws: nothing.

-
-

weak_ptr constructor

-
template<class Y> explicit shared_ptr(weak_ptr<Y> const & r);
-
-

Requires: Y* should be convertible to T*.

-

Effects: Constructs a shared_ptr that shares ownership with - r and stores a copy of the pointer stored in r.

-

Postconditions: use_count() == r.use_count().

-

Throws: bad_weak_ptr when r.use_count() == 0.

-

Exception safety: If an exception is thrown, the constructor has no - effect.

-
-

auto_ptr constructors

-
template<class Y> shared_ptr(std::auto_ptr<Y> & r);
+        
+

Requires: Y* should be convertible to T*.

+

Effects: Move-constructs a shared_ptr from r.

+

Postconditions: *this contains the old value of r. r is empty and r.get() == 0.

+

Throws: nothing.

+
+

aliasing constructor

+
template<class Y> shared_ptr(shared_ptr<Y> const & r, element_type * p); // never throws
+
+

Effects: constructs a shared_ptr that shares ownership with + r and stores p.

+

Postconditions: get() == p && use_count() == r.use_count().

+

Throws: nothing.

+
+

weak_ptr constructor

+
template<class Y> explicit shared_ptr(weak_ptr<Y> const & r);
+
+

Requires: Y* should be convertible to T*.

+

Effects: Constructs a shared_ptr that shares ownership with + r and stores a copy of the pointer stored in r.

+

Postconditions: use_count() == r.use_count().

+

Throws: bad_weak_ptr when r.use_count() == 0.

+

Exception safety: If an exception is thrown, the constructor has no + effect.

+
+

auto_ptr constructors

+
template<class Y> shared_ptr(std::auto_ptr<Y> & r);
 template<class Y> shared_ptr(std::auto_ptr<Y> && r);
-
-

Requires: Y* should be convertible to T*.

-

Effects: Constructs a shared_ptr, as if by storing a copy of r.release().

-

Postconditions: use_count() == 1.

-

Throws: std::bad_alloc, or an implementation-defined - exception when a resource other than memory could not be obtained.

-

Exception safety: If an exception is thrown, the constructor has no - effect.

-
-

unique_ptr constructor

-
template<class Y, class D> shared_ptr(std::unique_ptr<Y, D> && r);
-
-

Requires: Y* should be convertible to T*.

-

Effects: - Equivalent to shared_ptr(r.release(), r.get_deleter()) when D is not a reference type. - Otherwise, equivalent to shared_ptr(r.release(), del), where del is a deleter - that stores the reference rd returned from r.get_deleter() and del(p) calls rd(p).

-

Postconditions: use_count() == 1.

-

Throws: std::bad_alloc, or an implementation-defined - exception when a resource other than memory could not be obtained.

-

Exception safety: If an exception is thrown, the constructor has no - effect.

-
-

destructor

-
~shared_ptr(); // never throws
-
-

Effects:

-
    -
  • - If *this is empty, or shares ownership with - another shared_ptr instance (use_count() > 1), - there are no side effects.
  • -
  • - Otherwise, if *this owns a pointer p - and a deleter d, d(p) - is called.
  • -
  • - Otherwise, *this owns a pointer p, - and delete p is called.
  • -
-

Throws: nothing.

-
-

assignment

-
shared_ptr & operator=(shared_ptr const & r); // never throws
+        
+

Requires: Y* should be convertible to T*.

+

Effects: Constructs a shared_ptr, as if by storing a copy of r.release().

+

Postconditions: use_count() == 1.

+

Throws: std::bad_alloc, or an implementation-defined + exception when a resource other than memory could not be obtained.

+

Exception safety: If an exception is thrown, the constructor has no + effect.

+
+

unique_ptr constructor

+
template<class Y, class D> shared_ptr(std::unique_ptr<Y, D> && r);
+
+

Requires: Y* should be convertible to T*.

+

Effects: + Equivalent to shared_ptr(r.release(), r.get_deleter()) when D is not a reference type. + Otherwise, equivalent to shared_ptr(r.release(), del), where del is a deleter + that stores the reference rd returned from r.get_deleter() and del(p) calls rd(p).

+

Postconditions: use_count() == 1.

+

Throws: std::bad_alloc, or an implementation-defined + exception when a resource other than memory could not be obtained.

+

Exception safety: If an exception is thrown, the constructor has no + effect.

+
+

destructor

+
~shared_ptr(); // never throws
+
+

Effects:

+
    +
  • + If *this is empty, or shares ownership with + another shared_ptr instance (use_count() > 1), + there are no side effects.
  • +
  • + Otherwise, if *this owns a pointer p + and a deleter d, d(p) + is called.
  • +
  • + Otherwise, *this owns a pointer p, + and delete p is called.
  • +
+

Throws: nothing.

+
+

assignment

+
shared_ptr & operator=(shared_ptr const & r); // never throws
 template<class Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws
 template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & r);
-
-

Effects: Equivalent to shared_ptr(r).swap(*this).

-

Returns: *this.

-

Notes: The use count updates caused by the temporary object construction - and destruction are not considered observable side effects, and the - implementation is free to meet the effects (and the implied guarantees) via - different means, without creating a temporary. In particular, in the example:

-
shared_ptr<int> p(new int);
+        
+

Effects: Equivalent to shared_ptr(r).swap(*this).

+

Returns: *this.

+

Notes: The use count updates caused by the temporary object construction + and destruction are not considered observable side effects, and the + implementation is free to meet the effects (and the implied guarantees) via + different means, without creating a temporary. In particular, in the example:

+
shared_ptr<int> p(new int);
 shared_ptr<void> q(p);
 p = p;
 q = p;
 
-

both assignments may be no-ops.

-
-
shared_ptr & operator=(shared_ptr && r); // never throws
+            

both assignments may be no-ops.

+
+
shared_ptr & operator=(shared_ptr && r); // never throws
 template<class Y> shared_ptr & operator=(shared_ptr<Y> && r); // never throws
 template<class Y> shared_ptr & operator=(std::auto_ptr<Y> && r);
 template<class Y, class D> shared_ptr & operator=(std::unique_ptr<Y, D> && r);
-
-

Effects: Equivalent to shared_ptr(std::move(r)).swap(*this).

-

Returns: *this.

-
-
shared_ptr & operator=(std::nullptr_t); // never throws
-
-

Effects: Equivalent to shared_ptr().swap(*this).

-

Returns: *this.

-
-

reset

-
void reset(); // never throws
-
-

Effects: Equivalent to shared_ptr().swap(*this).

-
-
template<class Y> void reset(Y * p);
-
-

Effects: Equivalent to shared_ptr(p).swap(*this).

-
-
template<class Y, class D> void reset(Y * p, D d);
-
-

Effects: Equivalent to shared_ptr(p, d).swap(*this).

-
-
template<class Y, class D, class A> void reset(Y * p, D d, A a);
-
-

Effects: Equivalent to shared_ptr(p, d, a).swap(*this).

-
-
template<class Y> void reset(shared_ptr<Y> const & r, element_type * p); // never throws
-
-

Effects: Equivalent to shared_ptr(r, p).swap(*this).

-
-

indirection

-
T & operator*() const; // never throws
-
-

Requirements: T should not be an array type. The stored pointer must not be 0.

-

Returns: a reference to the object pointed to by the stored pointer.

-

Throws: nothing.

-
-
T * operator->() const; // never throws
-
-

Requirements: T should not be an array type. The stored pointer must not be 0.

-

Returns: the stored pointer.

-

Throws: nothing.

-
-
element_type & operator[](std::ptrdiff_t i) const; // never throws
-
-

Requirements: T should be an array type. The stored pointer must not be 0. - i >= 0. If T is U[N], i < N.

-

Returns: get()[i].

-

Throws: nothing.

-
-

get

-
element_type * get() const; // never throws
-
-

Returns: the stored pointer.

-

Throws: nothing.

-
-

unique

-
bool unique() const; // never throws
-
-

Returns: use_count() == 1.

-

Throws: nothing.

-

Notes: unique() may be faster than use_count(). - If you are using unique() to implement copy on write, do not rely - on a specific value when the stored pointer is zero.

-
-

use_count

-
long use_count() const; // never throws
-
-

Returns: the number of shared_ptr objects, *this included, - that share ownership with *this, or 0 when *this - is empty.

-

Throws: nothing.

-

Notes: use_count() is not necessarily efficient. Use only - for debugging and testing purposes, not for production code.

-
-

conversions

-
explicit operator bool() const; // never throws
-
-

Returns: get() != 0.

-

Throws: nothing.

-

Notes: This conversion operator allows shared_ptr objects to be - used in boolean contexts, like if(p && p->valid()) {}.

-
-

[The conversion to bool is not merely syntactic sugar. It allows shared_ptrs - to be declared in conditions when using dynamic_pointer_cast - or weak_ptr::lock.]

-

swap

-
void swap(shared_ptr & b); // never throws
-
-

Effects: Exchanges the contents of the two smart pointers.

-

Throws: nothing.

-
-

swap

+
+

Effects: Equivalent to shared_ptr(std::move(r)).swap(*this).

+

Returns: *this.

+
+
shared_ptr & operator=(std::nullptr_t); // never throws
+
+

Effects: Equivalent to shared_ptr().swap(*this).

+

Returns: *this.

+
+

reset

+
void reset(); // never throws
+
+

Effects: Equivalent to shared_ptr().swap(*this).

+
+
template<class Y> void reset(Y * p);
+
+

Effects: Equivalent to shared_ptr(p).swap(*this).

+
+
template<class Y, class D> void reset(Y * p, D d);
+
+

Effects: Equivalent to shared_ptr(p, d).swap(*this).

+
+
template<class Y, class D, class A> void reset(Y * p, D d, A a);
+
+

Effects: Equivalent to shared_ptr(p, d, a).swap(*this).

+
+
template<class Y> void reset(shared_ptr<Y> const & r, element_type * p); // never throws
+
+

Effects: Equivalent to shared_ptr(r, p).swap(*this).

+
+

indirection

+
T & operator*() const; // never throws
+
+

Requirements: T should not be an array type. The stored pointer must not be 0.

+

Returns: a reference to the object pointed to by the stored pointer.

+

Throws: nothing.

+
+
T * operator->() const; // never throws
+
+

Requirements: T should not be an array type. The stored pointer must not be 0.

+

Returns: the stored pointer.

+

Throws: nothing.

+
+
element_type & operator[](std::ptrdiff_t i) const; // never throws
+
+

Requirements: T should be an array type. The stored pointer must not be 0. + i >= 0. If T is U[N], i < N.

+

Returns: get()[i].

+

Throws: nothing.

+
+

get

+
element_type * get() const; // never throws
+
+

Returns: the stored pointer.

+

Throws: nothing.

+
+

unique

+
bool unique() const; // never throws
+
+

Returns: use_count() == 1.

+

Throws: nothing.

+

Notes: unique() may be faster than use_count(). + If you are using unique() to implement copy on write, do not rely + on a specific value when the stored pointer is zero.

+
+

use_count

+
long use_count() const; // never throws
+
+

Returns: the number of shared_ptr objects, *this included, + that share ownership with *this, or 0 when *this + is empty.

+

Throws: nothing.

+

Notes: use_count() is not necessarily efficient. Use only + for debugging and testing purposes, not for production code.

+
+

conversions

+
explicit operator bool() const; // never throws
+
+

Returns: get() != 0.

+

Throws: nothing.

+

Notes: This conversion operator allows shared_ptr objects to be + used in boolean contexts, like if(p && p->valid()) {}.

+
+

[The conversion to bool is not merely syntactic sugar. It allows shared_ptrs + to be declared in conditions when using dynamic_pointer_cast + or weak_ptr::lock.]

+

swap

+
void swap(shared_ptr & b); // never throws
+
+

Effects: Exchanges the contents of the two smart pointers.

+

Throws: nothing.

+
+

swap

template<class Y> bool owner_before(shared_ptr<Y> const & rhs) const; // never throws
 template<class Y> bool owner_before(weak_ptr<Y> const & rhs) const; // never throws
-
-

Effects: See the description of operator<.

-

Throws: nothing.

-
-

Free Functions

-

comparison

-
template<class T, class U>
+        
+

Effects: See the description of operator<.

+

Throws: nothing.

+
+

Free Functions

+

comparison

+
template<class T, class U>
   bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
-
-

Returns: a.get() == b.get().

-

Throws: nothing.

-
-
template<class T, class U>
+        
+

Returns: a.get() == b.get().

+

Throws: nothing.

+
+
template<class T, class U>
   bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
-
-

Returns: a.get() != b.get().

-

Throws: nothing.

-
+
+

Returns: a.get() != b.get().

+

Throws: nothing.

+
template<class T>
   bool operator==(shared_ptr<T> const & p, std::nullptr_t); // never throws
 template<class T>
   bool operator==(std::nullptr_t, shared_ptr<T> const & p); // never throws
-
-

Returns: p.get() == 0.

-

Throws: nothing.

-
+
+

Returns: p.get() == 0.

+

Throws: nothing.

+
template<class T>
   bool operator!=(shared_ptr<T> const & p, std::nullptr_t); // never throws
 template<class T>
   bool operator!=(std::nullptr_t, shared_ptr<T> const & p); // never throws
-
-

Returns: p.get() != 0.

-

Throws: nothing.

-
-
template<class T, class U>
+        
+

Returns: p.get() != 0.

+

Throws: nothing.

+
+
template<class T, class U>
   bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
-
-

Returns: an unspecified value such that

-
    -
  • - operator< is a strict weak ordering as described in section 25.3 [lib.alg.sorting] - of the C++ standard;
  • -
  • - under the equivalence relation defined by operator<, !(a - < b) && !(b < a), two shared_ptr instances - are equivalent if and only if they share ownership or are both empty.
-

Throws: nothing.

-

Notes: Allows shared_ptr objects to be used as keys in - associative containers.

-
-

[Operator< has been preferred over a std::less - specialization for consistency and legality reasons, as std::less - is required to return the results of operator<, and many - standard algorithms use operator< instead of std::less - for comparisons when a predicate is not supplied. Composite objects, like std::pair, - also implement their operator< in terms of their contained - subobjects' operator<.

-

The rest of the comparison operators are omitted by design.]

-

swap

-
template<class T>
+        
+

Returns: an unspecified value such that

+
    +
  • + operator< is a strict weak ordering as described in section 25.3 [lib.alg.sorting] + of the C++ standard;
  • +
  • + under the equivalence relation defined by operator<, !(a + < b) && !(b < a), two shared_ptr instances + are equivalent if and only if they share ownership or are both empty.
+

Throws: nothing.

+

Notes: Allows shared_ptr objects to be used as keys in + associative containers.

+
+

[Operator< has been preferred over a std::less + specialization for consistency and legality reasons, as std::less + is required to return the results of operator<, and many + standard algorithms use operator< instead of std::less + for comparisons when a predicate is not supplied. Composite objects, like std::pair, + also implement their operator< in terms of their contained + subobjects' operator<.

+

The rest of the comparison operators are omitted by design.]

+

swap

+
template<class T>
   void swap(shared_ptr<T> & a, shared_ptr<T> & b); // never throws
-
-

Effects: Equivalent to a.swap(b).

-

Throws: nothing.

-

Notes: Matches the interface of std::swap. Provided as an aid to - generic programming.

-
-

[swap is defined in the same namespace as shared_ptr - as this is currently the only legal way to supply a swap function - that has a chance to be used by the standard library.]

-

get_pointer

-
template<class T>
+        
+

Effects: Equivalent to a.swap(b).

+

Throws: nothing.

+

Notes: Matches the interface of std::swap. Provided as an aid to + generic programming.

+
+

[swap is defined in the same namespace as shared_ptr + as this is currently the only legal way to supply a swap function + that has a chance to be used by the standard library.]

+

get_pointer

+
template<class T>
   typename shared_ptr<T>::element_type * get_pointer(shared_ptr<T> const & p); // never throws
-
-

Returns: p.get().

-

Throws: nothing.

-

Notes: Provided as an aid to generic programming. Used by - mem_fn.

-
-

static_pointer_cast

-
template<class T, class U>
+        
+

Returns: p.get().

+

Throws: nothing.

+

Notes: Provided as an aid to generic programming. Used by + mem_fn.

+
+

static_pointer_cast

+
template<class T, class U>
   shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r); // never throws
-
-

Requires: The expression static_cast<T*>( (U*)0 ) - must be well-formed.

-

Returns: shared_ptr<T>( r, static_cast<typename shared_ptr<T>::element_type*>(r.get()) ).

-

Throws: nothing.

-

Notes: the seemingly equivalent expression - shared_ptr<T>(static_cast<T*>(r.get())) - will eventually result in undefined behavior, attempting to delete the same - object twice.

-
-

const_pointer_cast

-
template<class T, class U>
+        
+

Requires: The expression static_cast<T*>( (U*)0 ) + must be well-formed.

+

Returns: shared_ptr<T>( r, static_cast<typename shared_ptr<T>::element_type*>(r.get()) ).

+

Throws: nothing.

+

Notes: the seemingly equivalent expression + shared_ptr<T>(static_cast<T*>(r.get())) + will eventually result in undefined behavior, attempting to delete the same + object twice.

+
+

const_pointer_cast

+
template<class T, class U>
   shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r); // never throws
-
-

Requires: The expression const_cast<T*>( (U*)0 ) - must be well-formed.

-

Returns: shared_ptr<T>( r, const_cast<typename shared_ptr<T>::element_type*>(r.get()) ).

-

Throws: nothing.

-
-

dynamic_pointer_cast

-
template<class T, class U>
+        
+

Requires: The expression const_cast<T*>( (U*)0 ) + must be well-formed.

+

Returns: shared_ptr<T>( r, const_cast<typename shared_ptr<T>::element_type*>(r.get()) ).

+

Throws: nothing.

+
+

dynamic_pointer_cast

+
template<class T, class U>
   shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r);
-
-

Requires: The expression dynamic_cast<T*>( (U*)0 ) - must be well-formed.

-

Returns:

-
    -
  • - When dynamic_cast<typename shared_ptr<T>::element_type*>(r.get()) returns a nonzero value p, - shared_ptr<T>(r, p);
  • -
  • - Otherwise, shared_ptr<T>().
-

Throws: nothing.

-
-

reinterpret_pointer_cast

-
template<class T, class U>
+        
+

Requires: The expression dynamic_cast<T*>( (U*)0 ) + must be well-formed.

+

Returns:

+
    +
  • + When dynamic_cast<typename shared_ptr<T>::element_type*>(r.get()) returns a nonzero value p, + shared_ptr<T>(r, p);
  • +
  • + Otherwise, shared_ptr<T>().
+

Throws: nothing.

+
+

reinterpret_pointer_cast

+
template<class T, class U>
   shared_ptr<T> reinterpret_pointer_cast(shared_ptr<U> const & r); // never throws
-
-

Requires: The expression reinterpret_cast<T*>( (U*)0 ) - must be well-formed.

-

Returns: shared_ptr<T>( r, reinterpret_cast<typename shared_ptr<T>::element_type*>(r.get()) ).

-

Throws: nothing.

-
-

operator<<

-
template<class E, class T, class Y>
+        
+

Requires: The expression reinterpret_cast<T*>( (U*)0 ) + must be well-formed.

+

Returns: shared_ptr<T>( r, reinterpret_cast<typename shared_ptr<T>::element_type*>(r.get()) ).

+

Throws: nothing.

+
+

operator<<

+
template<class E, class T, class Y>
     std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p);
-
-

Effects: os << p.get();.

-

Returns: os.

-
-

get_deleter

-
template<class D, class T>
+        
+

Effects: os << p.get();.

+

Returns: os.

+
+

get_deleter

+
template<class D, class T>
     D * get_deleter(shared_ptr<T> const & p);
-
-

Returns: If *this owns a deleter d - of type (cv-unqualified) D, returns &d; - otherwise returns 0.

-

Throws: nothing.

-
-

Example

-

See shared_ptr_example.cpp for a - complete example program. The program builds a std::vector and std::set - of shared_ptr objects.

-

Note that after the containers have been populated, some of the shared_ptr - objects will have a use count of 1 rather than a use count of 2, since the set - is a std::set rather than a std::multiset, and thus does not - contain duplicate entries. Furthermore, the use count may be even higher at - various times while push_back and insert container operations are - performed. More complicated yet, the container operations may throw exceptions - under a variety of circumstances. Getting the memory management and exception - handling in this example right without a smart pointer would be a nightmare.

-

Handle/Body Idiom

-

One common usage of shared_ptr is to implement a handle/body (also called - pimpl) idiom which avoids exposing the body (implementation) in the header - file.

-

The shared_ptr_example2_test.cpp - sample program includes a header file, shared_ptr_example2.hpp, - which uses a shared_ptr to an incomplete type to hide the - implementation. The instantiation of member functions which require a complete - type occurs in the shared_ptr_example2.cpp - implementation file. Note that there is no need for an explicit destructor. - Unlike ~scoped_ptr, ~shared_ptr does not require that T be a complete - type.

-

Thread Safety

-

shared_ptr objects offer the same level of thread safety as - built-in types. A shared_ptr instance can be "read" (accessed - using only const operations) simultaneously by multiple threads. Different shared_ptr - instances can be "written to" (accessed using mutable operations such as operator= - or reset) simultaneously by multiple threads (even - when these instances are copies, and share the same reference count - underneath.)

-

Any other simultaneous accesses result in undefined behavior.

-

Examples:

-
shared_ptr<int> p(new int(42));
+        
+

Returns: If *this owns a deleter d + of type (cv-unqualified) D, returns &d; + otherwise returns 0.

+

Throws: nothing.

+
+

Example

+

See shared_ptr_example.cpp for a + complete example program. The program builds a std::vector and std::set + of shared_ptr objects.

+

Note that after the containers have been populated, some of the shared_ptr + objects will have a use count of 1 rather than a use count of 2, since the set + is a std::set rather than a std::multiset, and thus does not + contain duplicate entries. Furthermore, the use count may be even higher at + various times while push_back and insert container operations are + performed. More complicated yet, the container operations may throw exceptions + under a variety of circumstances. Getting the memory management and exception + handling in this example right without a smart pointer would be a nightmare.

+

Handle/Body Idiom

+

One common usage of shared_ptr is to implement a handle/body (also called + pimpl) idiom which avoids exposing the body (implementation) in the header + file.

+

The shared_ptr_example2_test.cpp + sample program includes a header file, shared_ptr_example2.hpp, + which uses a shared_ptr to an incomplete type to hide the + implementation. The instantiation of member functions which require a complete + type occurs in the shared_ptr_example2.cpp + implementation file. Note that there is no need for an explicit destructor. + Unlike ~scoped_ptr, ~shared_ptr does not require that T be a complete + type.

+

Thread Safety

+

shared_ptr objects offer the same level of thread safety as + built-in types. A shared_ptr instance can be "read" (accessed + using only const operations) simultaneously by multiple threads. Different shared_ptr + instances can be "written to" (accessed using mutable operations such as operator= + or reset) simultaneously by multiple threads (even + when these instances are copies, and share the same reference count + underneath.)

+

Any other simultaneous accesses result in undefined behavior.

+

Examples:

+
shared_ptr<int> p(new int(42));
 
 //--- Example 1 ---
 
@@ -741,104 +742,105 @@ p3.reset(new int(1));
 // thread B
 p3.reset(new int(2)); // undefined, multiple writes
 
-

 

-

Starting with Boost release 1.33.0, shared_ptr uses a lock-free - implementation on most common platforms.

-

If your program is single-threaded and does not link to any libraries that might - have used shared_ptr in its default configuration, you can - #define the macro BOOST_SP_DISABLE_THREADS on a - project-wide basis to switch to ordinary non-atomic reference count updates.

-

(Defining BOOST_SP_DISABLE_THREADS in some, but not all, - translation units is technically a violation of the One Definition Rule and - undefined behavior. Nevertheless, the implementation attempts to do its best to - accommodate the request to use non-atomic updates in those translation units. - No guarantees, though.)

-

You can define the macro BOOST_SP_USE_PTHREADS to turn off the - lock-free platform-specific implementation and fall back to the generic - pthread_mutex_t-based code.

-

Frequently Asked Questions

-

Q. There are several variations of shared pointers, with different - tradeoffs; why does the smart pointer library supply only a single - implementation? It would be useful to be able to experiment with each type so - as to find the most suitable for the job at hand?

-

- A. An important goal of shared_ptr is to provide a - standard shared-ownership pointer. Having a single pointer type is important - for stable library interfaces, since different shared pointers typically cannot - interoperate, i.e. a reference counted pointer (used by library A) cannot share - ownership with a linked pointer (used by library B.) -

-

Q. Why doesn't shared_ptr have template parameters supplying - traits or policies to allow extensive user customization?

-

- A. Parameterization discourages users. The shared_ptr template is - carefully crafted to meet common needs without extensive parameterization. Some - day a highly configurable smart pointer may be invented that is also very easy - to use and very hard to misuse. Until then, shared_ptr is the smart - pointer of choice for a wide range of applications. (Those interested in policy - based smart pointers should read - Modern C++ Design by Andrei Alexandrescu.) -

-

Q. I am not convinced. Default parameters can be used where appropriate - to hide the complexity. Again, why not policies?

-

- A. Template parameters affect the type. See the answer to the first - question above. -

-

Q. Why doesn't shared_ptr use a linked list implementation?

-

- A. A linked list implementation does not offer enough advantages to - offset the added cost of an extra pointer. See timings - page. In addition, it is expensive to make a linked list implementation thread - safe. -

-

Q. Why doesn't shared_ptr (or any of the other Boost smart - pointers) supply an automatic conversion to T*?

-

- A. Automatic conversion is believed to be too error prone. -

-

Q. Why does shared_ptr supply use_count()?

-

- A. As an aid to writing test cases and debugging displays. One of the - progenitors had use_count(), and it was useful in tracking down bugs in a - complex project that turned out to have cyclic-dependencies. -

-

Q. Why doesn't shared_ptr specify complexity requirements?

-

- A. Because complexity requirements limit implementors and complicate the - specification without apparent benefit to shared_ptr users. For example, - error-checking implementations might become non-conforming if they had to meet - stringent complexity requirements. -

-

Q. Why doesn't shared_ptr provide a release() function?

-

- A. shared_ptr cannot give away ownership unless it's unique() - because the other copy will still destroy the object.

-

Consider:

-
shared_ptr<int> a(new int);
+        

 

+

Starting with Boost release 1.33.0, shared_ptr uses a lock-free + implementation on most common platforms.

+

If your program is single-threaded and does not link to any libraries that might + have used shared_ptr in its default configuration, you can + #define the macro BOOST_SP_DISABLE_THREADS on a + project-wide basis to switch to ordinary non-atomic reference count updates.

+

(Defining BOOST_SP_DISABLE_THREADS in some, but not all, + translation units is technically a violation of the One Definition Rule and + undefined behavior. Nevertheless, the implementation attempts to do its best to + accommodate the request to use non-atomic updates in those translation units. + No guarantees, though.)

+

You can define the macro BOOST_SP_USE_PTHREADS to turn off the + lock-free platform-specific implementation and fall back to the generic + pthread_mutex_t-based code.

+

Frequently Asked Questions

+

Q. There are several variations of shared pointers, with different + tradeoffs; why does the smart pointer library supply only a single + implementation? It would be useful to be able to experiment with each type so + as to find the most suitable for the job at hand?

+

+ A. An important goal of shared_ptr is to provide a + standard shared-ownership pointer. Having a single pointer type is important + for stable library interfaces, since different shared pointers typically cannot + interoperate, i.e. a reference counted pointer (used by library A) cannot share + ownership with a linked pointer (used by library B.) +

+

Q. Why doesn't shared_ptr have template parameters supplying + traits or policies to allow extensive user customization?

+

+ A. Parameterization discourages users. The shared_ptr template is + carefully crafted to meet common needs without extensive parameterization. Some + day a highly configurable smart pointer may be invented that is also very easy + to use and very hard to misuse. Until then, shared_ptr is the smart + pointer of choice for a wide range of applications. (Those interested in policy + based smart pointers should read + Modern C++ Design by Andrei Alexandrescu.) +

+

Q. I am not convinced. Default parameters can be used where appropriate + to hide the complexity. Again, why not policies?

+

+ A. Template parameters affect the type. See the answer to the first + question above. +

+

Q. Why doesn't shared_ptr use a linked list implementation?

+

+ A. A linked list implementation does not offer enough advantages to + offset the added cost of an extra pointer. See timings + page. In addition, it is expensive to make a linked list implementation thread + safe. +

+

Q. Why doesn't shared_ptr (or any of the other Boost smart + pointers) supply an automatic conversion to T*?

+

+ A. Automatic conversion is believed to be too error prone. +

+

Q. Why does shared_ptr supply use_count()?

+

+ A. As an aid to writing test cases and debugging displays. One of the + progenitors had use_count(), and it was useful in tracking down bugs in a + complex project that turned out to have cyclic-dependencies. +

+

Q. Why doesn't shared_ptr specify complexity requirements?

+

+ A. Because complexity requirements limit implementors and complicate the + specification without apparent benefit to shared_ptr users. For example, + error-checking implementations might become non-conforming if they had to meet + stringent complexity requirements. +

+

Q. Why doesn't shared_ptr provide a release() function?

+

+ A. shared_ptr cannot give away ownership unless it's unique() + because the other copy will still destroy the object.

+

Consider:

+
shared_ptr<int> a(new int);
 shared_ptr<int> b(a); // a.use_count() == b.use_count() == 2
 
 int * p = a.release();
 
 // Who owns p now? b will still call delete on it in its destructor.
-
-

Furthermore, the pointer returned by release() would be difficult - to deallocate reliably, as the source shared_ptr could have been created - with a custom deleter. -

-

Q. Why is operator->() const, but its return value is a - non-const pointer to the element type?

-

- A. Shallow copy pointers, including raw pointers, typically don't - propagate constness. It makes little sense for them to do so, as you can always - obtain a non-const pointer from a const one and then proceed to modify the - object through it. shared_ptr is "as close to raw pointers as possible - but no closer". -

-
-

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. - Copyright 2002-2005, 2012, 2013 Peter Dimov. 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.

- +
+

Furthermore, the pointer returned by release() would be difficult + to deallocate reliably, as the source shared_ptr could have been created + with a custom deleter. +

+

Q. Why is operator->() const, but its return value is a + non-const pointer to the element type?

+

+ A. Shallow copy pointers, including raw pointers, typically don't + propagate constness. It makes little sense for them to do so, as you can always + obtain a non-const pointer from a const one and then proceed to modify the + object through it. shared_ptr is "as close to raw pointers as possible + but no closer". +

+
+

$Date$

+

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. + Copyright 2002-2005, 2012, 2013 Peter Dimov. 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.

+ diff --git a/smart_ptr.htm b/smart_ptr.htm index 3956aaf..fab9dd6 100644 --- a/smart_ptr.htm +++ b/smart_ptr.htm @@ -1,216 +1,221 @@ - - Smart Pointers - - - -

boost.png (6897 bytes)Smart Pointers

-

Introduction
- Common Requirements
- Exception Safety
- Exception-specifications
- History and Acknowledgements
- References

-

Introduction

-

Smart pointers are objects which store pointers to dynamically allocated (heap) - objects. They behave much like built-in C++ pointers except that they - automatically delete the object pointed to at the appropriate time. Smart - pointers are particularly useful in the face of exceptions as they ensure - proper destruction of dynamically allocated objects. They can also be used to - keep track of dynamically allocated objects shared by multiple owners.

-

Conceptually, smart pointers are seen as owning the object pointed to, and thus - responsible for deletion of the object when it is no longer needed.

-

The smart pointer library provides six smart pointer class templates:

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
scoped_ptr<boost/scoped_ptr.hpp>Simple sole ownership of single objects. Noncopyable.
scoped_array<boost/scoped_array.hpp>Simple sole ownership of arrays. Noncopyable.
shared_ptr<boost/shared_ptr.hpp>Object ownership shared among multiple pointers.
shared_array<boost/shared_array.hpp>Array ownership shared among multiple pointers.
weak_ptr<boost/weak_ptr.hpp>Non-owning observers of an object owned by shared_ptr.
intrusive_ptr<boost/intrusive_ptr.hpp>Shared ownership of objects with an embedded reference count.
-
-

These templates are designed to complement the std::auto_ptr template.

-

They are examples of the "resource acquisition is initialization" idiom - described in Bjarne Stroustrup's "The C++ Programming Language", 3rd edition, - Section 14.4, Resource Management.

-

Additionally, the smart pointer library provides efficient factory functions - for creating smart pointer objects:

-
- - - - - - - - - - - - - - - - -
make_shared and allocate_shared for objects<boost/make_shared.hpp>Efficient creation of shared_ptr objects.
make_shared and allocate_shared for arrays<boost/make_shared.hpp>Efficient creation of shared_ptr arrays.
make_unique<boost/make_unique.hpp>Creation of unique_ptr objects and arrays.
-
-

A test program, smart_ptr_test.cpp, is - provided to verify correct operation.

-

A page on compatibility with older versions of - the Boost smart pointer library describes some of the changes since earlier - versions of the smart pointer implementation.

-

A page on smart pointer timings will be of interest - to those curious about performance issues.

-

A page on smart pointer programming techniques lists - some advanced applications of shared_ptr and weak_ptr.

-

Common Requirements

-

These smart pointer class templates have a template parameter, T, which - specifies the type of the object pointed to by the smart pointer. The behavior - of the smart pointer templates is undefined if the destructor or operator delete - for objects of type T throw exceptions.

-

T may be an incomplete type at the point of smart pointer declaration. - Unless otherwise specified, it is required that T be a complete type at - points of smart pointer instantiation. Implementations are required to diagnose - (treat as an error) all violations of this requirement, including deletion of - an incomplete type. See the description of the - checked_delete function template.

-

Note that shared_ptr does not have this restriction, as most of - its member functions do not require T to be a complete type.

-

Rationale

-

The requirements on T are carefully crafted to maximize safety yet allow - handle-body (also called pimpl) and similar idioms. In these idioms a smart - pointer may appear in translation units where T is an incomplete type. - This separates interface from implementation and hides implementation from - translation units which merely use the interface. Examples described in the - documentation for specific smart pointers illustrate use of smart pointers in - these idioms.

-

Note that scoped_ptr requires that T be a complete type at - destruction time, but shared_ptr does not.

-

Exception Safety

-

Several functions in these smart pointer classes are specified as having "no - effect" or "no effect except such-and-such" if an exception is thrown. This - means that when an exception is thrown by an object of one of these classes, - the entire program state remains the same as it was prior to the function call - which resulted in the exception being thrown. This amounts to a guarantee that - there are no detectable side effects. Other functions never throw exceptions. - The only exception ever thrown by functions which do throw (assuming T meets - the common requirements) is std::bad_alloc, - and that is thrown only by functions which are explicitly documented as - possibly throwing std::bad_alloc.

-

Exception-specifications

-

Exception-specifications are not used; see - exception-specification rationale.

-

All the smart pointer templates contain member functions which can never throw - exceptions, because they neither throw exceptions themselves nor call other - functions which may throw exceptions. These members are indicated by a comment: - // never throws. -

-

Functions which destroy objects of the pointed to type are prohibited from - throwing exceptions by the common requirements.

-

History and Acknowledgements

-

January 2014. Glen Fernandes confined the overloads of make_shared - and allocate_shared for arrays to the specification in - N3870 - and implemented make_unique for arrays and objects.

-

November 2012. Glen Fernandes provided implementations of make_shared - and allocate_shared for arrays. They achieve a single allocation for an - array that can be initialized with constructor arguments or initializer lists - as well as overloads for default initialization and no value initialization. - See the make_shared and allocate_shared for - arrays page for more information.

-

January 2002. Peter Dimov reworked all four classes, adding features, fixing - bugs, and splitting them into four separate headers, and added weak_ptr. - See the compatibility page for a summary of the - changes.

-

May 2001. Vladimir Prus suggested requiring a complete type on destruction. - Refinement evolved in discussions including Dave Abrahams, Greg Colvin, Beman - Dawes, Rainer Deyke, Peter Dimov, John Maddock, Vladimir Prus, Shankar Sai, and - others.

-

November 1999. Darin Adler provided operator ==, operator !=, and std::swap - and std::less specializations for shared types.

-

September 1999. Luis Coelho provided shared_ptr::swap and shared_array::swap

-

May 1999. In April and May, 1999, Valentin Bonnard and David Abrahams made a - number of suggestions resulting in numerous improvements.

-

October 1998. Beman Dawes proposed reviving the original semantics under the - names safe_ptr and counted_ptr, meeting of Per Andersson, Matt - Austern, Greg Colvin, Sean Corfield, Pete Becker, Nico Josuttis, Dietmar Kühl, - Nathan Myers, Chichiang Wan and Judy Ward. During the discussion, the four new - class names were finalized, it was decided that there was no need to exactly - follow the std::auto_ptr interface, and various function signatures and - semantics were finalized.

-

Over the next three months, several implementations were considered for shared_ptr, - and discussed on the boost.org mailing list. - The implementation questions revolved around the reference count which must be - kept, either attached to the pointed to object, or detached elsewhere. Each of - those variants have themselves two major variants: -

    -
  • - Direct detached: the shared_ptr contains a pointer to the object, and a pointer - to the count. -
  • - Indirect detached: the shared_ptr contains a pointer to a helper object, which - in turn contains a pointer to the object and the count. -
  • - Embedded attached: the count is a member of the object pointed to. -
  • - Placement attached: the count is attached via operator new manipulations.
  • -
-

Each implementation technique has advantages and disadvantages. We went so far - as to run various timings of the direct and indirect approaches, and found that - at least on Intel Pentium chips there was very little measurable difference. - Kevlin Henney provided a paper he wrote on "Counted Body Techniques." Dietmar - Kühl suggested an elegant partial template specialization technique to allow - users to choose which implementation they preferred, and that was also - experimented with.

-

But Greg Colvin and Jerry Schwarz argued that "parameterization will discourage - users", and in the end we choose to supply only the direct implementation.

-

Summer, 1994. Greg Colvin proposed to the C++ Standards Committee classes named auto_ptr - and counted_ptr which were very similar to what we now call scoped_ptr - and shared_ptr. [Col-94] In one of the very few - cases where the Library Working Group's recommendations were not followed by - the full committee, counted_ptr was rejected and surprising - transfer-of-ownership semantics were added to auto_ptr.

-

References

-

[Col-94] Gregory Colvin, - Exception Safe Smart Pointers, C++ committee document 94-168/N0555, - July, 1994.

-

[E&D-94] John R. Ellis & David L. Detlefs, - Safe, Efficient Garbage Collection for C++, Usenix Proceedings, - February, 1994. This paper includes an extensive discussion of weak pointers - and an extensive bibliography.

-
-

$Date$

-

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. - 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.

- + + Smart Pointers + + + +

boost.png (6897 bytes)Smart Pointers

+

Introduction
+ Common Requirements
+ Exception Safety
+ Exception-specifications
+ History and Acknowledgements
+ References

+

Introduction

+

Smart pointers are objects which store pointers to dynamically allocated (heap) + objects. They behave much like built-in C++ pointers except that they + automatically delete the object pointed to at the appropriate time. Smart + pointers are particularly useful in the face of exceptions as they ensure + proper destruction of dynamically allocated objects. They can also be used to + keep track of dynamically allocated objects shared by multiple owners.

+

Conceptually, smart pointers are seen as owning the object pointed to, and thus + responsible for deletion of the object when it is no longer needed.

+

The smart pointer library provides six smart pointer class templates:

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
scoped_ptr<boost/scoped_ptr.hpp>Simple sole ownership of single objects. Noncopyable.
scoped_array<boost/scoped_array.hpp>Simple sole ownership of arrays. Noncopyable.
shared_ptr<boost/shared_ptr.hpp>Object ownership shared among multiple pointers.
shared_array<boost/shared_array.hpp>Array ownership shared among multiple pointers.
weak_ptr<boost/weak_ptr.hpp>Non-owning observers of an object owned by shared_ptr.
intrusive_ptr<boost/intrusive_ptr.hpp>Shared ownership of objects with an embedded reference count.
+
+

These templates are designed to complement the std::auto_ptr template.

+

They are examples of the "resource acquisition is initialization" idiom + described in Bjarne Stroustrup's "The C++ Programming Language", 3rd edition, + Section 14.4, Resource Management.

+

Additionally, the smart pointer library provides efficient factory functions + for creating smart pointer objects:

+
+ + + + + + + + + + + + + + + + +
make_shared, allocate_shared for objects<boost/make_shared.hpp>Efficient creation of shared_ptr objects.
make_shared, allocate_shared for arrays<boost/make_shared.hpp>Efficient creation of shared_ptr arrays.
make_unique<boost/make_unique.hpp>Creation of unique_ptr objects and arrays.
+
+

A test program, smart_ptr_test.cpp, is + provided to verify correct operation.

+

A page on compatibility with older versions of + the Boost smart pointer library describes some of the changes since earlier + versions of the smart pointer implementation.

+

A page on smart pointer timings will be of interest + to those curious about performance issues.

+

A page on smart pointer programming techniques lists + some advanced applications of shared_ptr and weak_ptr.

+

Common Requirements

+

These smart pointer class templates have a template parameter, T, which + specifies the type of the object pointed to by the smart pointer. The behavior + of the smart pointer templates is undefined if the destructor or operator delete + for objects of type T throw exceptions.

+

T may be an incomplete type at the point of smart pointer declaration. + Unless otherwise specified, it is required that T be a complete type at + points of smart pointer instantiation. Implementations are required to diagnose + (treat as an error) all violations of this requirement, including deletion of + an incomplete type. See the description of the + checked_delete function template.

+

Note that shared_ptr does not have this restriction, as most of + its member functions do not require T to be a complete type.

+

Rationale

+

The requirements on T are carefully crafted to maximize safety yet allow + handle-body (also called pimpl) and similar idioms. In these idioms a smart + pointer may appear in translation units where T is an incomplete type. + This separates interface from implementation and hides implementation from + translation units which merely use the interface. Examples described in the + documentation for specific smart pointers illustrate use of smart pointers in + these idioms.

+

Note that scoped_ptr requires that T be a complete type at + destruction time, but shared_ptr does not.

+

Exception Safety

+

Several functions in these smart pointer classes are specified as having "no + effect" or "no effect except such-and-such" if an exception is thrown. This + means that when an exception is thrown by an object of one of these classes, + the entire program state remains the same as it was prior to the function call + which resulted in the exception being thrown. This amounts to a guarantee that + there are no detectable side effects. Other functions never throw exceptions. + The only exception ever thrown by functions which do throw (assuming T meets + the common requirements) is std::bad_alloc, + and that is thrown only by functions which are explicitly documented as + possibly throwing std::bad_alloc.

+

Exception-specifications

+

Exception-specifications are not used; see + exception-specification rationale.

+

All the smart pointer templates contain member functions which can never throw + exceptions, because they neither throw exceptions themselves nor call other + functions which may throw exceptions. These members are indicated by a comment: + // never throws. +

+

Functions which destroy objects of the pointed to type are prohibited from + throwing exceptions by the common requirements.

+

History and Acknowledgements

+

February 2014. Glen Fernandes updated overloads of make_shared and + allocate_shared to conform to the specification in C++ standard paper + [D&F-14], and implemented make_unique for + arrays and objects. Peter Dimov and Glen Fernandes updated the scalar and + array implementations, respectively, to resolve C++ standard library defect + 2070.

+

November 2012. Glen Fernandes provided implementations of make_shared + and allocate_shared for arrays. They achieve a single allocation for an + array that can be initialized with constructor arguments or initializer lists + as well as overloads for default initialization and no value initialization. + See the make_shared and allocate_shared for + arrays page for more information.

+

January 2002. Peter Dimov reworked all four classes, adding features, fixing + bugs, and splitting them into four separate headers, and added weak_ptr. + See the compatibility page for a summary of the + changes.

+

May 2001. Vladimir Prus suggested requiring a complete type on destruction. + Refinement evolved in discussions including Dave Abrahams, Greg Colvin, Beman + Dawes, Rainer Deyke, Peter Dimov, John Maddock, Vladimir Prus, Shankar Sai, and + others.

+

November 1999. Darin Adler provided operator ==, operator !=, and std::swap + and std::less specializations for shared types.

+

September 1999. Luis Coelho provided shared_ptr::swap and shared_array::swap

+

May 1999. In April and May, 1999, Valentin Bonnard and David Abrahams made a + number of suggestions resulting in numerous improvements.

+

October 1998. Beman Dawes proposed reviving the original semantics under the + names safe_ptr and counted_ptr, meeting of Per Andersson, Matt + Austern, Greg Colvin, Sean Corfield, Pete Becker, Nico Josuttis, Dietmar Kühl, + Nathan Myers, Chichiang Wan and Judy Ward. During the discussion, the four new + class names were finalized, it was decided that there was no need to exactly + follow the std::auto_ptr interface, and various function signatures and + semantics were finalized.

+

Over the next three months, several implementations were considered for shared_ptr, + and discussed on the boost.org mailing list. + The implementation questions revolved around the reference count which must be + kept, either attached to the pointed to object, or detached elsewhere. Each of + those variants have themselves two major variants: +

    +
  • + Direct detached: the shared_ptr contains a pointer to the object, and a pointer + to the count. +
  • + Indirect detached: the shared_ptr contains a pointer to a helper object, which + in turn contains a pointer to the object and the count. +
  • + Embedded attached: the count is a member of the object pointed to. +
  • + Placement attached: the count is attached via operator new manipulations.
  • +
+

Each implementation technique has advantages and disadvantages. We went so far + as to run various timings of the direct and indirect approaches, and found that + at least on Intel Pentium chips there was very little measurable difference. + Kevlin Henney provided a paper he wrote on "Counted Body Techniques." Dietmar + Kühl suggested an elegant partial template specialization technique to allow + users to choose which implementation they preferred, and that was also + experimented with.

+

But Greg Colvin and Jerry Schwarz argued that "parameterization will discourage + users", and in the end we choose to supply only the direct implementation.

+

Summer, 1994. Greg Colvin proposed to the C++ Standards Committee classes named auto_ptr + and counted_ptr which were very similar to what we now call scoped_ptr + and shared_ptr. [Col-94] In one of the very few + cases where the Library Working Group's recommendations were not followed by + the full committee, counted_ptr was rejected and surprising + transfer-of-ownership semantics were added to auto_ptr.

+

References

+

[D&F-14] Peter Dimov & Glen Fernandes, + Extending make_shared to Support Arrays, Revision 1, C++ committee document N3870, + January, 2014.

+

[Col-94] Gregory Colvin, + Exception Safe Smart Pointers, C++ committee document 94-168/N0555, + July, 1994.

+

[E&D-94] John R. Ellis & David L. Detlefs, + Safe, Efficient Garbage Collection for C++, Usenix Proceedings, + February, 1994. This paper includes an extensive discussion of weak pointers + and an extensive bibliography.

+
+

$Date$

+

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. + 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.

+ diff --git a/smarttests.htm b/smarttests.htm index 1833719..2551ae4 100644 --- a/smarttests.htm +++ b/smarttests.htm @@ -7,9 +7,9 @@ - - -

boost.png (6897 bytes)Smart Pointer Timings

+ + +

boost.png (6897 bytes)Smart Pointer Timings

In late January 2000, Mark Borgerding put forward a suggestion to boost for a new design of smart pointer whereby an intrusive doubly linked list is used @@ -533,9 +533,8 @@ Gavin Collings, spreads its information as in the case of linked pointer.


-

Revised 19 August 2001 -

-

© Copyright Gavin Collings 2000. Permission to copy, use, modify, sell +

$Date$

+

© Copyright Gavin Collings 2000. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided "as is" without express or implied warranty, and with no claim as to its suitability for any purpose.

diff --git a/sp_techniques.html b/sp_techniques.html index f869279..7e0ce8f 100644 --- a/sp_techniques.html +++ b/sp_techniques.html @@ -1,67 +1,67 @@ - + - - Smart Pointer Programming Techniques - - - -

boost.png (6897 bytes)Smart Pointer Programming Techniques

-

Using incomplete classes for implementation hiding
- The "Pimpl" idiom
- Using abstract classes for implementation hiding
- Preventing delete px.get()
- Using a shared_ptr to hold a pointer to an array
- Encapsulating allocation details, wrapping factory - functions
- Using a shared_ptr to hold a pointer to a statically - allocated object
- Using a shared_ptr to hold a pointer to a COM object
- Using a shared_ptr to hold a pointer to an object - with an embedded reference count
- Using a shared_ptr to hold another shared - ownership smart pointer
- Obtaining a shared_ptr from a raw pointer
- Obtaining a shared_ptr (weak_ptr) - to this in a constructor
- Obtaining a shared_ptr to this
- Using shared_ptr as a smart counted handle
- Using shared_ptr to execute code on block - exit
- Using shared_ptr<void> to hold an arbitrary - object
- Associating arbitrary data with heterogeneous shared_ptr - instances
- Using shared_ptr as a CopyConstructible mutex lock
- Using shared_ptr to wrap member function calls
- Delayed deallocation
- Weak pointers to objects not managed by a shared_ptr
-

-

Using incomplete classes for implementation hiding

-

A proven technique (that works in C, too) for separating interface from - implementation is to use a pointer to an incomplete class as an opaque handle:

-
class FILE;
+    
+        Smart Pointer Programming Techniques
+        
+    
+    
+        

boost.png (6897 bytes)Smart Pointer Programming Techniques

+

Using incomplete classes for implementation hiding
+ The "Pimpl" idiom
+ Using abstract classes for implementation hiding
+ Preventing delete px.get()
+ Using a shared_ptr to hold a pointer to an array
+ Encapsulating allocation details, wrapping factory + functions
+ Using a shared_ptr to hold a pointer to a statically + allocated object
+ Using a shared_ptr to hold a pointer to a COM object
+ Using a shared_ptr to hold a pointer to an object + with an embedded reference count
+ Using a shared_ptr to hold another shared + ownership smart pointer
+ Obtaining a shared_ptr from a raw pointer
+ Obtaining a shared_ptr (weak_ptr) + to this in a constructor
+ Obtaining a shared_ptr to this
+ Using shared_ptr as a smart counted handle
+ Using shared_ptr to execute code on block + exit
+ Using shared_ptr<void> to hold an arbitrary + object
+ Associating arbitrary data with heterogeneous shared_ptr + instances
+ Using shared_ptr as a CopyConstructible mutex lock
+ Using shared_ptr to wrap member function calls
+ Delayed deallocation
+ Weak pointers to objects not managed by a shared_ptr
+

+

Using incomplete classes for implementation hiding

+

A proven technique (that works in C, too) for separating interface from + implementation is to use a pointer to an incomplete class as an opaque handle:

+
class FILE;
 
 FILE * fopen(char const * name, char const * mode);
 void fread(FILE * f, void * data, size_t size);
 void fclose(FILE * f);
 
-

It is possible to express the above interface using shared_ptr, - eliminating the need to manually call fclose:

-
class FILE;
+        

It is possible to express the above interface using shared_ptr, + eliminating the need to manually call fclose:

+
class FILE;
 
 shared_ptr<FILE> fopen(char const * name, char const * mode);
 void fread(shared_ptr<FILE> f, void * data, size_t size);
 
-

This technique relies on shared_ptr's ability to execute a custom - deleter, eliminating the explicit call to fclose, and on the fact - that shared_ptr<X> can be copied and destroyed when X - is incomplete.

-

The "Pimpl" idiom

-

A C++ specific variation of the incomplete class pattern is the "Pimpl" idiom. - The incomplete class is not exposed to the user; it is hidden behind a - forwarding facade. shared_ptr can be used to implement a "Pimpl":

-
// file.hpp:
+        

This technique relies on shared_ptr's ability to execute a custom + deleter, eliminating the explicit call to fclose, and on the fact + that shared_ptr<X> can be copied and destroyed when X + is incomplete.

+

The "Pimpl" idiom

+

A C++ specific variation of the incomplete class pattern is the "Pimpl" idiom. + The incomplete class is not exposed to the user; it is hidden behind a + forwarding facade. shared_ptr can be used to implement a "Pimpl":

+
// file.hpp:
 
 class file
 {
@@ -79,7 +79,7 @@ public:
     void read(void * data, size_t size);
 };
 
-
// file.cpp:
+        
// file.cpp:
 
 #include "file.hpp"
 
@@ -108,17 +108,17 @@ void file::read(void * data, size_t size)
     pimpl_->read(data, size);
 }
 
-

The key thing to note here is that the compiler-generated copy constructor, - assignment operator, and destructor all have a sensible meaning. As a result, - file is CopyConstructible and Assignable, - allowing its use in standard containers.

-

Using abstract classes for implementation hiding

-

Another widely used C++ idiom for separating inteface and implementation is to - use abstract base classes and factory functions. The abstract classes are - sometimes called "interfaces" and the pattern is known as "interface-based - programming". Again, shared_ptr can be used as the return type of - the factory functions:

-
// X.hpp:
+        

The key thing to note here is that the compiler-generated copy constructor, + assignment operator, and destructor all have a sensible meaning. As a result, + file is CopyConstructible and Assignable, + allowing its use in standard containers.

+

Using abstract classes for implementation hiding

+

Another widely used C++ idiom for separating inteface and implementation is to + use abstract base classes and factory functions. The abstract classes are + sometimes called "interfaces" and the pattern is known as "interface-based + programming". Again, shared_ptr can be used as the return type of + the factory functions:

+
// X.hpp:
 
 class X
 {
@@ -134,7 +134,7 @@ protected:
 
 shared_ptr<X> createX();
 
-
-- X.cpp:
+        
-- X.cpp:
 
 class X_impl: public X
 {
@@ -162,18 +162,18 @@ shared_ptr<X> createX()
     return px;
 }
 
-

A key property of shared_ptr is that the allocation, construction, deallocation, - and destruction details are captured at the point of construction, inside the - factory function. Note the protected and nonvirtual destructor in the example - above. The client code cannot, and does not need to, delete a pointer to X; - the shared_ptr<X> instance returned from createX - will correctly call ~X_impl.

-

Preventing delete px.get()

-

It is often desirable to prevent client code from deleting a pointer that is - being managed by shared_ptr. The previous technique showed one - possible approach, using a protected destructor. Another alternative is to use - a private deleter:

-
class X
+        

A key property of shared_ptr is that the allocation, construction, deallocation, + and destruction details are captured at the point of construction, inside the + factory function. Note the protected and nonvirtual destructor in the example + above. The client code cannot, and does not need to, delete a pointer to X; + the shared_ptr<X> instance returned from createX + will correctly call ~X_impl.

+

Preventing delete px.get()

+

It is often desirable to prevent client code from deleting a pointer that is + being managed by shared_ptr. The previous technique showed one + possible approach, using a protected destructor. Another alternative is to use + a private deleter:

+
class X
 {
 private:
 
@@ -198,48 +198,48 @@ public:
     }
 };
 
-

Using a shared_ptr to hold a pointer to an array

-

A shared_ptr can be used to hold a pointer to an array allocated - with new[]:

-
shared_ptr<X> px(new X[1], checked_array_deleter<X>());
+        

Using a shared_ptr to hold a pointer to an array

+

A shared_ptr can be used to hold a pointer to an array allocated + with new[]:

+
shared_ptr<X> px(new X[1], checked_array_deleter<X>());
 
-

Note, however, that shared_array is - often preferable, if this is an option. It has an array-specific interface, - without operator* and operator->, and does not - allow pointer conversions.

-

Encapsulating allocation details, wrapping factory - functions

-

shared_ptr can be used in creating C++ wrappers over existing C - style library interfaces that return raw pointers from their factory functions - to encapsulate allocation details. As an example, consider this interface, - where CreateX might allocate X from its own private - heap, ~X may be inaccessible, or X may be incomplete:

-
X * CreateX();
+        

Note, however, that shared_array is + often preferable, if this is an option. It has an array-specific interface, + without operator* and operator->, and does not + allow pointer conversions.

+

Encapsulating allocation details, wrapping factory + functions

+

shared_ptr can be used in creating C++ wrappers over existing C + style library interfaces that return raw pointers from their factory functions + to encapsulate allocation details. As an example, consider this interface, + where CreateX might allocate X from its own private + heap, ~X may be inaccessible, or X may be incomplete:

+
X * CreateX();
 void DestroyX(X *);
 
-

The only way to reliably destroy a pointer returned by CreateX is - to call DestroyX.

-

Here is how a shared_ptr-based wrapper may look like:

-
shared_ptr<X> createX()
+        

The only way to reliably destroy a pointer returned by CreateX is + to call DestroyX.

+

Here is how a shared_ptr-based wrapper may look like:

+
shared_ptr<X> createX()
 {
     shared_ptr<X> px(CreateX(), DestroyX);
     return px;
 }
 
-

Client code that calls createX still does not need to know how the - object has been allocated, but now the destruction is automatic.

-

Using a shared_ptr to hold a pointer to a statically - allocated object

-

Sometimes it is desirable to create a shared_ptr to an already - existing object, so that the shared_ptr does not attempt to - destroy the object when there are no more references left. As an example, the - factory function:

-
shared_ptr<X> createX();
+        

Client code that calls createX still does not need to know how the + object has been allocated, but now the destruction is automatic.

+

Using a shared_ptr to hold a pointer to a statically + allocated object

+

Sometimes it is desirable to create a shared_ptr to an already + existing object, so that the shared_ptr does not attempt to + destroy the object when there are no more references left. As an example, the + factory function:

+
shared_ptr<X> createX();
 
-

in certain situations may need to return a pointer to a statically allocated X - instance.

-

The solution is to use a custom deleter that does nothing:

-
struct null_deleter
+        

in certain situations may need to return a pointer to a statically allocated X + instance.

+

The solution is to use a custom deleter that does nothing:

+
struct null_deleter
 {
     void operator()(void const *) const
     {
@@ -254,33 +254,33 @@ shared_ptr<X> createX()
     return px;
 }
 
-

The same technique works for any object known to outlive the pointer.

-

Using a shared_ptr to hold a pointer to a COM Object

-

Background: COM objects have an embedded reference count and two member - functions that manipulate it. AddRef() increments the count. Release() - decrements the count and destroys itself when the count drops to zero.

-

It is possible to hold a pointer to a COM object in a shared_ptr:

-
shared_ptr<IWhatever> make_shared_from_COM(IWhatever * p)
+        

The same technique works for any object known to outlive the pointer.

+

Using a shared_ptr to hold a pointer to a COM Object

+

Background: COM objects have an embedded reference count and two member + functions that manipulate it. AddRef() increments the count. Release() + decrements the count and destroys itself when the count drops to zero.

+

It is possible to hold a pointer to a COM object in a shared_ptr:

+
shared_ptr<IWhatever> make_shared_from_COM(IWhatever * p)
 {
     p->AddRef();
     shared_ptr<IWhatever> pw(p, mem_fn(&IWhatever::Release));
     return pw;
 }
 
-

Note, however, that shared_ptr copies created from pw will - not "register" in the embedded count of the COM object; they will share the - single reference created in make_shared_from_COM. Weak pointers - created from pw will be invalidated when the last shared_ptr - is destroyed, regardless of whether the COM object itself is still alive.

-

As explained in the mem_fn documentation, - you need to #define - BOOST_MEM_FN_ENABLE_STDCALL first.

-

Using a shared_ptr to hold a pointer to an object - with an embedded reference count

-

This is a generalization of the above technique. The example assumes that the - object implements the two functions required by intrusive_ptr, - intrusive_ptr_add_ref and intrusive_ptr_release:

-
template<class T> struct intrusive_deleter
+        

Note, however, that shared_ptr copies created from pw will + not "register" in the embedded count of the COM object; they will share the + single reference created in make_shared_from_COM. Weak pointers + created from pw will be invalidated when the last shared_ptr + is destroyed, regardless of whether the COM object itself is still alive.

+

As explained in the mem_fn documentation, + you need to #define + BOOST_MEM_FN_ENABLE_STDCALL first.

+

Using a shared_ptr to hold a pointer to an object + with an embedded reference count

+

This is a generalization of the above technique. The example assumes that the + object implements the two functions required by intrusive_ptr, + intrusive_ptr_add_ref and intrusive_ptr_release:

+
template<class T> struct intrusive_deleter
 {
     void operator()(T * p)
     {
@@ -295,15 +295,15 @@ shared_ptr<X> make_shared_from_intrusive(X * p)
     return px;
 }
 
-

Using a shared_ptr to hold another shared - ownership smart pointer

-

One of the design goals of shared_ptr is to be used in library - interfaces. It is possible to encounter a situation where a library takes a shared_ptr - argument, but the object at hand is being managed by a different reference - counted or linked smart pointer.

-

It is possible to exploit shared_ptr's custom deleter feature to - wrap this existing smart pointer behind a shared_ptr facade:

-
template<class P> struct smart_pointer_deleter
+        

Using a shared_ptr to hold another shared + ownership smart pointer

+

One of the design goals of shared_ptr is to be used in library + interfaces. It is possible to encounter a situation where a library takes a shared_ptr + argument, but the object at hand is being managed by a different reference + counted or linked smart pointer.

+

It is possible to exploit shared_ptr's custom deleter feature to + wrap this existing smart pointer behind a shared_ptr facade:

+
template<class P> struct smart_pointer_deleter
 {
 private:
 
@@ -332,17 +332,17 @@ shared_ptr<X> make_shared_from_another(another_ptr<X> qx)
     return px;
 }
 
-

One subtle point is that deleters are not allowed to throw exceptions, and the - above example as written assumes that p_.reset() doesn't throw. If - this is not the case, p_.reset() should be wrapped in a try {} - catch(...) {} block that ignores exceptions. In the (usually - unlikely) event when an exception is thrown and ignored, p_ will - be released when the lifetime of the deleter ends. This happens when all - references, including weak pointers, are destroyed or reset.

-

Another twist is that it is possible, given the above shared_ptr instance, - to recover the original smart pointer, using - get_deleter:

-
void extract_another_from_shared(shared_ptr<X> px)
+        

One subtle point is that deleters are not allowed to throw exceptions, and the + above example as written assumes that p_.reset() doesn't throw. If + this is not the case, p_.reset() should be wrapped in a try {} + catch(...) {} block that ignores exceptions. In the (usually + unlikely) event when an exception is thrown and ignored, p_ will + be released when the lifetime of the deleter ends. This happens when all + references, including weak pointers, are destroyed or reset.

+

Another twist is that it is possible, given the above shared_ptr instance, + to recover the original smart pointer, using + get_deleter:

+
void extract_another_from_shared(shared_ptr<X> px)
 {
     typedef smart_pointer_deleter< another_ptr<X> > deleter;
 
@@ -356,37 +356,37 @@ shared_ptr<X> make_shared_from_another(another_ptr<X> qx)
     }
 }
 
-

Obtaining a shared_ptr from a raw pointer

-

Sometimes it is necessary to obtain a shared_ptr given a raw - pointer to an object that is already managed by another shared_ptr - instance. Example:

-
void f(X * p)
+        

Obtaining a shared_ptr from a raw pointer

+

Sometimes it is necessary to obtain a shared_ptr given a raw + pointer to an object that is already managed by another shared_ptr + instance. Example:

+
void f(X * p)
 {
     shared_ptr<X> px(???);
 }
 
-

Inside f, we'd like to create a shared_ptr to *p.

-

In the general case, this problem has no solution. One approach is to modify f - to take a shared_ptr, if possible:

-
void f(shared_ptr<X> px);
+        

Inside f, we'd like to create a shared_ptr to *p.

+

In the general case, this problem has no solution. One approach is to modify f + to take a shared_ptr, if possible:

+
void f(shared_ptr<X> px);
 
-

The same transformation can be used for nonvirtual member functions, to convert - the implicit this:

-
void X::f(int m);
+        

The same transformation can be used for nonvirtual member functions, to convert + the implicit this:

+
void X::f(int m);
 
-

would become a free function with a shared_ptr first argument:

-
void f(shared_ptr<X> this_, int m);
+        

would become a free function with a shared_ptr first argument:

+
void f(shared_ptr<X> this_, int m);
 
-

If f cannot be changed, but X uses intrusive counting, - use make_shared_from_intrusive described - above. Or, if it's known that the shared_ptr created in f - will never outlive the object, use a null deleter.

-

Obtaining a shared_ptr (weak_ptr) - to this in a constructor

-

Some designs require objects to register themselves on construction with a - central authority. When the registration routines take a shared_ptr, this leads - to the question how could a constructor obtain a shared_ptr to this:

-
class X
+        

If f cannot be changed, but X uses intrusive counting, + use make_shared_from_intrusive described + above. Or, if it's known that the shared_ptr created in f + will never outlive the object, use a null deleter.

+

Obtaining a shared_ptr (weak_ptr) + to this in a constructor

+

Some designs require objects to register themselves on construction with a + central authority. When the registration routines take a shared_ptr, this leads + to the question how could a constructor obtain a shared_ptr to this:

+
class X
 {
 public:
 
@@ -396,19 +396,19 @@ public:
     }
 };
 
-

In the general case, the problem cannot be solved. The X instance - being constructed can be an automatic variable or a static variable; it can be - created on the heap:

-
shared_ptr<X> px(new X);
-

but at construction time, px does not exist yet, and it is - impossible to create another shared_ptr instance that shares - ownership with it.

-

Depending on context, if the inner shared_ptr this_ doesn't - need to keep the object alive, use a null_deleter as explained - here and here. If X is - supposed to always live on the heap, and be managed by a shared_ptr, - use a static factory function:

-
class X
+        

In the general case, the problem cannot be solved. The X instance + being constructed can be an automatic variable or a static variable; it can be + created on the heap:

+
shared_ptr<X> px(new X);
+

but at construction time, px does not exist yet, and it is + impossible to create another shared_ptr instance that shares + ownership with it.

+

Depending on context, if the inner shared_ptr this_ doesn't + need to keep the object alive, use a null_deleter as explained + here and here. If X is + supposed to always live on the heap, and be managed by a shared_ptr, + use a static factory function:

+
class X
 {
 private:
 
@@ -424,13 +424,13 @@ public:
     }
 };
 
-

Obtaining a shared_ptr to this

-

Sometimes it is needed to obtain a shared_ptr from this - in a virtual member function under the assumption that this is - already managed by a shared_ptr. The transformations - described in the previous technique cannot be applied.

-

A typical example:

-
class X
+        

Obtaining a shared_ptr to this

+

Sometimes it is needed to obtain a shared_ptr from this + in a virtual member function under the assumption that this is + already managed by a shared_ptr. The transformations + described in the previous technique cannot be applied.

+

A typical example:

+
class X
 {
 public:
 
@@ -469,8 +469,8 @@ public:
     }
 };
 
-

The solution is to keep a weak pointer to this as a member in impl:

-
class impl: public X, public Y
+        

The solution is to keep a weak pointer to this as a member in impl:

+
class impl: public X, public Y
 {
 private:
 
@@ -499,10 +499,10 @@ public:
     }
 };
 
-

The library now includes a helper class template - enable_shared_from_this that can be used to encapsulate the - solution:

-
class impl: public X, public Y, public enable_shared_from_this<impl>
+        

The library now includes a helper class template + enable_shared_from_this that can be used to encapsulate the + solution:

+
class impl: public X, public Y, public enable_shared_from_this<impl>
 {
 public:
 
@@ -519,19 +519,19 @@ public:
     }
 }
 
-

Note that you no longer need to manually initialize the weak_ptr member - in enable_shared_from_this. - Constructing a shared_ptr to impl takes care of that.

-

Using shared_ptr as a smart counted handle

-

Some library interfaces use opaque handles, a variation of the - incomplete class technique described above. An example:

-
typedef void * HANDLE;
+        

Note that you no longer need to manually initialize the weak_ptr member + in enable_shared_from_this. + Constructing a shared_ptr to impl takes care of that.

+

Using shared_ptr as a smart counted handle

+

Some library interfaces use opaque handles, a variation of the + incomplete class technique described above. An example:

+
typedef void * HANDLE;
 HANDLE CreateProcess();
 void CloseHandle(HANDLE);
 
-

Instead of a raw pointer, it is possible to use shared_ptr as the - handle and get reference counting and automatic resource management for free:

-
typedef shared_ptr<void> handle;
+        

Instead of a raw pointer, it is possible to use shared_ptr as the + handle and get reference counting and automatic resource management for free:

+
typedef shared_ptr<void> handle;
 
 handle createProcess()
 {
@@ -539,42 +539,42 @@ handle createProcess()
     return pv;
 }
 
-

Using shared_ptr to execute code on block exit

-

shared_ptr<void> can automatically execute cleanup code when - control leaves a scope.

-
    -
  • - Executing f(p), where p is a pointer:
-
    shared_ptr<void> guard(p, f);
+        

Using shared_ptr to execute code on block exit

+

shared_ptr<void> can automatically execute cleanup code when + control leaves a scope.

+
    +
  • + Executing f(p), where p is a pointer:
+
    shared_ptr<void> guard(p, f);
 
-
    -
  • - Executing arbitrary code: f(x, y):
-
    shared_ptr<void> guard(static_cast<void*>(0), bind(f, x, y));
+        
    +
  • + Executing arbitrary code: f(x, y):
+
    shared_ptr<void> guard(static_cast<void*>(0), bind(f, x, y));
 
-

For a more thorough treatment, see the article "Simplify Your Exception-Safe - Code" by Andrei Alexandrescu and Petru Marginean, available online at - http://www.cuj.com/experts/1812/alexandr.htm?topic=experts.

-

Using shared_ptr<void> to hold an arbitrary - object

-

shared_ptr<void> can act as a generic object pointer similar - to void*. When a shared_ptr<void> instance - constructed as:

-
    shared_ptr<void> pv(new X);
+        

For a more thorough treatment, see the article "Simplify Your Exception-Safe + Code" by Andrei Alexandrescu and Petru Marginean, available online at + http://www.cuj.com/experts/1812/alexandr.htm?topic=experts.

+

Using shared_ptr<void> to hold an arbitrary + object

+

shared_ptr<void> can act as a generic object pointer similar + to void*. When a shared_ptr<void> instance + constructed as:

+
    shared_ptr<void> pv(new X);
 
-

is destroyed, it will correctly dispose of the X object by - executing ~X.

-

This propery can be used in much the same manner as a raw void* is - used to temporarily strip type information from an object pointer. A shared_ptr<void> - can later be cast back to the correct type by using - static_pointer_cast.

-

Associating arbitrary data with heterogeneous shared_ptr - instances

-

shared_ptr and weak_ptr support operator< - comparisons required by standard associative containers such as std::map. - This can be used to non-intrusively associate arbitrary data with objects - managed by shared_ptr:

-
typedef int Data;
+        

is destroyed, it will correctly dispose of the X object by + executing ~X.

+

This propery can be used in much the same manner as a raw void* is + used to temporarily strip type information from an object pointer. A shared_ptr<void> + can later be cast back to the correct type by using + static_pointer_cast.

+

Associating arbitrary data with heterogeneous shared_ptr + instances

+

shared_ptr and weak_ptr support operator< + comparisons required by standard associative containers such as std::map. + This can be used to non-intrusively associate arbitrary data with objects + managed by shared_ptr:

+
typedef int Data;
 
 std::map< shared_ptr<void>, Data > userData;
 // or std::map< weak_ptr<void>, Data > userData; to not affect the lifetime
@@ -585,11 +585,11 @@ shared_ptr<int> pi(new int(3));
 userData[px] = 42;
 userData[pi] = 91;
 
-

Using shared_ptr as a CopyConstructible mutex lock

-

Sometimes it's necessary to return a mutex lock from a function, and a - noncopyable lock cannot be returned by value. It is possible to use shared_ptr - as a mutex lock:

-
class mutex
+        

Using shared_ptr as a CopyConstructible mutex lock

+

Sometimes it's necessary to return a mutex lock from a function, and a + noncopyable lock cannot be returned by value. It is possible to use shared_ptr + as a mutex lock:

+
class mutex
 {
 public:
 
@@ -603,9 +603,9 @@ shared_ptr<mutex> lock(mutex & m)
     return shared_ptr<mutex>(&m, mem_fn(&mutex::unlock));
 }
 
-

Better yet, the shared_ptr instance acting as a lock can be - encapsulated in a dedicated shared_lock class:

-
class shared_lock
+        

Better yet, the shared_ptr instance acting as a lock can be + encapsulated in a dedicated shared_lock class:

+
class shared_lock
 {
 private:
 
@@ -616,17 +616,17 @@ public:
     template<class Mutex> explicit shared_lock(Mutex & m): pv((m.lock(), &m), mem_fn(&Mutex::unlock)) {}
 };
 
-

shared_lock can now be used as:

-
    shared_lock lock(m);
+        

shared_lock can now be used as:

+
    shared_lock lock(m);
 
-

Note that shared_lock is not templated on the mutex type, thanks to - shared_ptr<void>'s ability to hide type information.

-

Using shared_ptr to wrap member function calls

-

shared_ptr implements the ownership semantics required from the Wrap/CallProxy - scheme described in Bjarne Stroustrup's article "Wrapping C++ Member Function - Calls" (available online at http://www.stroustrup.com/wrapper.pdf). - An implementation is given below:

-
template<class T> class pointer
+        

Note that shared_lock is not templated on the mutex type, thanks to + shared_ptr<void>'s ability to hide type information.

+

Using shared_ptr to wrap member function calls

+

shared_ptr implements the ownership semantics required from the Wrap/CallProxy + scheme described in Bjarne Stroustrup's article "Wrapping C++ Member Function + Calls" (available online at http://www.stroustrup.com/wrapper.pdf). + An implementation is given below:

+
template<class T> class pointer
 {
 private:
 
@@ -669,10 +669,10 @@ int main()
     px->g();
 }
 
-

Delayed deallocation

-

In some situations, a single px.reset() can trigger an expensive - deallocation in a performance-critical region:

-
class X; // ~X is expensive
+        

Delayed deallocation

+

In some situations, a single px.reset() can trigger an expensive + deallocation in a performance-critical region:

+
class X; // ~X is expensive
 
 class Y
 {
@@ -686,10 +686,10 @@ public:
     }
 };
 
-

The solution is to postpone the potential deallocation by moving px - to a dedicated free list that can be periodically emptied when performance and - response times are not an issue:

-
vector< shared_ptr<void> > free_list;
+        

The solution is to postpone the potential deallocation by moving px + to a dedicated free list that can be periodically emptied when performance and + response times are not an issue:

+
vector< shared_ptr<void> > free_list;
 
 class Y
 {
@@ -706,9 +706,9 @@ public:
 
 // periodically invoke free_list.clear() when convenient
 
-

Another variation is to move the free list logic to the construction point by - using a delayed deleter:

-
struct delayed_deleter
+        

Another variation is to move the free list logic to the construction point by + using a delayed deleter:

+
struct delayed_deleter
 {
     template<class T> void operator()(T * p)
     {
@@ -723,9 +723,9 @@ public:
     }
 };
 
-

Weak pointers to objects not managed by a shared_ptr

-

Make the object hold a shared_ptr to itself, using a null_deleter:

-
class X
+        

Weak pointers to objects not managed by a shared_ptr

+

Make the object hold a shared_ptr to itself, using a null_deleter:

+
class X
 {
 private:
 
@@ -748,18 +748,18 @@ public:
 
     X & operator=(X const & rhs)
     {
-	    i_ = rhs.i_;
+        i_ = rhs.i_;
     }
 
     weak_ptr<X> get_weak_ptr() const { return this_; }
 };
 
-

When the object's lifetime ends, X::this_ will be destroyed, and - all weak pointers will automatically expire.

-
-

$Date$

-

Copyright © 2003 Peter Dimov. 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.

- +

When the object's lifetime ends, X::this_ will be destroyed, and + all weak pointers will automatically expire.

+
+

$Date$

+

Copyright © 2003 Peter Dimov. 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.

+ diff --git a/weak_ptr.htm b/weak_ptr.htm index 0fa87f7..4c256b8 100644 --- a/weak_ptr.htm +++ b/weak_ptr.htm @@ -1,42 +1,42 @@ - + - - weak_ptr - - - -

boost.png (6897 bytes)weak_ptr class template

-

Introduction
- Synopsis
- Members
- Free Functions
- Frequently Asked Questions -

-

Introduction

-

The weak_ptr class template stores a "weak reference" to an object that's - already managed by a shared_ptr. To access the object, a weak_ptr - can be converted to a shared_ptr using - the shared_ptr constructor or the member function - lock. When the last shared_ptr to the object goes - away and the object is deleted, the attempt to obtain a shared_ptr - from the weak_ptr instances that refer to the deleted object will fail: - the constructor will throw an exception of type boost::bad_weak_ptr, - and weak_ptr::lock will return an empty shared_ptr.

-

Every weak_ptr meets the CopyConstructible and Assignable requirements - of the C++ Standard Library, and so can be used in standard library containers. - Comparison operators are supplied so that weak_ptr works with the - standard library's associative containers.

-

weak_ptr operations never throw exceptions.

-

The class template is parameterized on T, the type of the object pointed - to.

-

Compared to shared_ptr, weak_ptr provides a - very limited subset of operations since accessing its stored pointer is often - dangerous in multithreaded programs, and sometimes unsafe even within a single - thread (that is, it may invoke undefined behavior.) Pretend for a moment that weak_ptr - has a get member function that returns a raw pointer, and consider this - innocent piece of code:

-
shared_ptr<int> p(new int(5));
+    
+        weak_ptr
+        
+    
+    
+        

boost.png (6897 bytes)weak_ptr class template

+

Introduction
+ Synopsis
+ Members
+ Free Functions
+ Frequently Asked Questions +

+

Introduction

+

The weak_ptr class template stores a "weak reference" to an object that's + already managed by a shared_ptr. To access the object, a weak_ptr + can be converted to a shared_ptr using + the shared_ptr constructor or the member function + lock. When the last shared_ptr to the object goes + away and the object is deleted, the attempt to obtain a shared_ptr + from the weak_ptr instances that refer to the deleted object will fail: + the constructor will throw an exception of type boost::bad_weak_ptr, + and weak_ptr::lock will return an empty shared_ptr.

+

Every weak_ptr meets the CopyConstructible and Assignable requirements + of the C++ Standard Library, and so can be used in standard library containers. + Comparison operators are supplied so that weak_ptr works with the + standard library's associative containers.

+

weak_ptr operations never throw exceptions.

+

The class template is parameterized on T, the type of the object pointed + to.

+

Compared to shared_ptr, weak_ptr provides a + very limited subset of operations since accessing its stored pointer is often + dangerous in multithreaded programs, and sometimes unsafe even within a single + thread (that is, it may invoke undefined behavior.) Pretend for a moment that weak_ptr + has a get member function that returns a raw pointer, and consider this + innocent piece of code:

+
shared_ptr<int> p(new int(5));
 weak_ptr<int> q(p);
 
 // some time later
@@ -46,12 +46,12 @@ if(int * r = q.get())
     // use *r
 }
 
-

Imagine that after the if, but immediately before r - is used, another thread executes the statement p.reset(). Now r - is a dangling pointer.

-

The solution to this problem is to create a temporary shared_ptr - from q:

-
shared_ptr<int> p(new int(5));
+        

Imagine that after the if, but immediately before r + is used, another thread executes the statement p.reset(). Now r + is a dangling pointer.

+

The solution to this problem is to create a temporary shared_ptr + from q:

+
shared_ptr<int> p(new int(5));
 weak_ptr<int> q(p);
 
 // some time later
@@ -61,13 +61,13 @@ if(shared_ptr<int> r = q.lock())
     // use *r
 }
 
-

Now r holds a reference to the object that was pointed by q. - Even if p.reset() is executed in another thread, the object will - stay alive until r goes out of scope or is reset. By obtaining - a shared_ptr to the object, we have effectively locked it - against destruction.

-

Synopsis

-
namespace boost {
+        

Now r holds a reference to the object that was pointed by q. + Even if p.reset() is executed in another thread, the object will + stay alive until r goes out of scope or is reset. By obtaining + a shared_ptr to the object, we have effectively locked it + against destruction.

+

Synopsis

+
namespace boost {
 
   template<class T> class weak_ptr {
 
@@ -101,119 +101,119 @@ if(shared_ptr<int> r = q.lock())
     void swap(weak_ptr<T> & a, weak_ptr<T> & b);
 }
 
-

Members

-

element_type

-
typedef T element_type;
-
-

Provides the type of the template parameter T.

-
-

constructors

-
weak_ptr();
-
-

Effects: Constructs an empty weak_ptr.

-

Postconditions: use_count() == 0.

-

Throws: nothing.

-
-
template<class Y> weak_ptr(shared_ptr<Y> const & r);
+        

Members

+

element_type

+
typedef T element_type;
+
+

Provides the type of the template parameter T.

+
+

constructors

+
weak_ptr();
+
+

Effects: Constructs an empty weak_ptr.

+

Postconditions: use_count() == 0.

+

Throws: nothing.

+
+
template<class Y> weak_ptr(shared_ptr<Y> const & r);
 weak_ptr(weak_ptr const & r);
 template<class Y> weak_ptr(weak_ptr<Y> const & r);
-
-

Effects: If r is empty, constructs an empty - weak_ptr; otherwise, constructs a weak_ptr that shares - ownership with r as if by storing a copy of the - pointer stored in r.

-

Postconditions: use_count() == r.use_count().

-

Throws: nothing.

-
-

destructor

-
~weak_ptr();
-
-

Effects: Destroys this weak_ptr but has no effect on the object - its stored pointer points to.

-

Throws: nothing.

-
-

assignment

-
weak_ptr & operator=(weak_ptr const & r);
+        
+

Effects: If r is empty, constructs an empty + weak_ptr; otherwise, constructs a weak_ptr that shares + ownership with r as if by storing a copy of the + pointer stored in r.

+

Postconditions: use_count() == r.use_count().

+

Throws: nothing.

+
+

destructor

+
~weak_ptr();
+
+

Effects: Destroys this weak_ptr but has no effect on the object + its stored pointer points to.

+

Throws: nothing.

+
+

assignment

+
weak_ptr & operator=(weak_ptr const & r);
 template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r);
 template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r);
-
-

Effects: Equivalent to weak_ptr(r).swap(*this).

-

Throws: nothing.

-

Notes: The implementation is free to meet the effects (and the implied - guarantees) via different means, without creating a temporary.

-
-

use_count

-
long use_count() const;
-
-

Returns: 0 if *this is empty; otherwise, the - number of shared_ptr objects that share ownership with *this.

-

Throws: nothing.

-

Notes: use_count() is not necessarily efficient. Use only - for debugging and testing purposes, not for production code.

-
-

expired

-
bool expired() const;
-
-

Returns: use_count() == 0.

-

Throws: nothing.

-

Notes: expired() may be faster than use_count().

-
-

lock

-
shared_ptr<T> lock() const;
-
-

Returns: expired()? shared_ptr<T>(): shared_ptr<T>(*this).

-

Throws: nothing.

-
-

reset

-
void reset();
-
-

Effects: Equivalent to weak_ptr().swap(*this).

-
-

swap

-
void swap(weak_ptr & b);
-
-

Effects: Exchanges the contents of the two smart pointers.

-

Throws: nothing.

-
-

Free Functions

-

comparison

-
template<class T, class U>
+        
+

Effects: Equivalent to weak_ptr(r).swap(*this).

+

Throws: nothing.

+

Notes: The implementation is free to meet the effects (and the implied + guarantees) via different means, without creating a temporary.

+
+

use_count

+
long use_count() const;
+
+

Returns: 0 if *this is empty; otherwise, the + number of shared_ptr objects that share ownership with *this.

+

Throws: nothing.

+

Notes: use_count() is not necessarily efficient. Use only + for debugging and testing purposes, not for production code.

+
+

expired

+
bool expired() const;
+
+

Returns: use_count() == 0.

+

Throws: nothing.

+

Notes: expired() may be faster than use_count().

+
+

lock

+
shared_ptr<T> lock() const;
+
+

Returns: expired()? shared_ptr<T>(): shared_ptr<T>(*this).

+

Throws: nothing.

+
+

reset

+
void reset();
+
+

Effects: Equivalent to weak_ptr().swap(*this).

+
+

swap

+
void swap(weak_ptr & b);
+
+

Effects: Exchanges the contents of the two smart pointers.

+

Throws: nothing.

+
+

Free Functions

+

comparison

+
template<class T, class U>
   bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b);
-
-

Returns: an unspecified value such that

-
    -
  • - operator< is a strict weak ordering as described in section 25.3 [lib.alg.sorting] - of the C++ standard; -
  • - under the equivalence relation defined by operator<, !(a - < b) && !(b < a), two weak_ptr instances - are equivalent if and only if they share ownership or are both empty.
-

Throws: nothing.

-

Notes: Allows weak_ptr objects to be used as keys in - associative containers.

-
-

swap

-
template<class T>
+        
+

Returns: an unspecified value such that

+
    +
  • + operator< is a strict weak ordering as described in section 25.3 [lib.alg.sorting] + of the C++ standard; +
  • + under the equivalence relation defined by operator<, !(a + < b) && !(b < a), two weak_ptr instances + are equivalent if and only if they share ownership or are both empty.
+

Throws: nothing.

+

Notes: Allows weak_ptr objects to be used as keys in + associative containers.

+
+

swap

+
template<class T>
   void swap(weak_ptr<T> & a, weak_ptr<T> & b)
-
-

Effects: Equivalent to a.swap(b).

-

Throws: nothing.

-

Notes: Matches the interface of std::swap. Provided as an aid to - generic programming.

-
-

Frequently Asked Questions

-

Q. Can an object create a weak_ptr to itself in its - constructor?

-

A. No. A weak_ptr can only be created from a shared_ptr, - and at object construction time no shared_ptr to the object - exists yet. Even if you could create a temporary shared_ptr to - this, it would go out of scope at the end of the constructor, and - all weak_ptr instances would instantly expire.

-

The solution is to make the constructor private, and supply a factory function - that returns a shared_ptr:
-

-
+        
+

Effects: Equivalent to a.swap(b).

+

Throws: nothing.

+

Notes: Matches the interface of std::swap. Provided as an aid to + generic programming.

+
+

Frequently Asked Questions

+

Q. Can an object create a weak_ptr to itself in its + constructor?

+

A. No. A weak_ptr can only be created from a shared_ptr, + and at object construction time no shared_ptr to the object + exists yet. Even if you could create a temporary shared_ptr to + this, it would go out of scope at the end of the constructor, and + all weak_ptr instances would instantly expire.

+

The solution is to make the constructor private, and supply a factory function + that returns a shared_ptr:
+

+
 class X
 {
 private:
@@ -230,13 +230,11 @@ public:
     }
 };
 
-


-

-
-

$Date$

-

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. - Copyright 2002-2005 Peter Dimov. 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.

- +
+

$Date$

+

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. + Copyright 2002-2005 Peter Dimov. 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.

+ From 6d73b4aa5441875a158ea3dcfcff5cd712cf552a Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Tue, 4 Feb 2014 23:36:04 -0800 Subject: [PATCH 32/39] Work around VC11 which has broken rebind_traits VC11 has only partial support for C++11 allocators. For example it has a non-conforming rebind_alloc and rebind_traits in std::allocator_traits because it does not support C++11 template aliases. --- .../smart_ptr/detail/array_allocator.hpp | 20 +- .../boost/smart_ptr/detail/array_deleter.hpp | 9 +- test/allocate_shared_array_construct_test.cpp | 191 ++++++++++++++---- 3 files changed, 167 insertions(+), 53 deletions(-) diff --git a/include/boost/smart_ptr/detail/array_allocator.hpp b/include/boost/smart_ptr/detail/array_allocator.hpp index 5c6baf4..f085523 100644 --- a/include/boost/smart_ptr/detail/array_allocator.hpp +++ b/include/boost/smart_ptr/detail/array_allocator.hpp @@ -12,7 +12,7 @@ #include #include #include -#if !defined(BOOST_NO_CXX11_ALLOCATOR) +#if !defined(BOOST_NO_CXX11_ALLOCATOR) #include #endif @@ -45,20 +45,20 @@ namespace boost { template friend class as_allocator; -#if !defined(BOOST_NO_CXX11_ALLOCATOR) +#if !defined(BOOST_NO_CXX11_ALLOCATOR) && \ + !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) typedef typename std::allocator_traits:: template rebind_alloc YA; typedef typename std::allocator_traits:: template rebind_alloc CA; - typedef typename std::allocator_traits:: - template rebind_traits YT; - typedef typename std::allocator_traits:: - template rebind_traits CT; #else - typedef typename A:: - template rebind::other YA; - typedef typename A:: - template rebind::other CA; + typedef typename A::template rebind::other YA; + typedef typename A::template rebind::other CA; +#endif + +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + typedef std::allocator_traits YT; + typedef std::allocator_traits CT; #endif public: diff --git a/include/boost/smart_ptr/detail/array_deleter.hpp b/include/boost/smart_ptr/detail/array_deleter.hpp index 5fd7e43..bf967a0 100644 --- a/include/boost/smart_ptr/detail/array_deleter.hpp +++ b/include/boost/smart_ptr/detail/array_deleter.hpp @@ -74,16 +74,19 @@ namespace boost { } private: -#if !defined(BOOST_NO_CXX11_ALLOCATOR) +#if !defined(BOOST_NO_CXX11_ALLOCATOR) && \ + !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) typedef typename std::allocator_traits:: template rebind_alloc TA; - typedef typename std::allocator_traits:: - template rebind_traits TT; #else typedef typename A:: template rebind::other TA; #endif +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + typedef std::allocator_traits TT; +#endif + void destroy(type*, std::size_t, boost::true_type) { } diff --git a/test/allocate_shared_array_construct_test.cpp b/test/allocate_shared_array_construct_test.cpp index 623aa65..6501fa0 100644 --- a/test/allocate_shared_array_construct_test.cpp +++ b/test/allocate_shared_array_construct_test.cpp @@ -10,11 +10,42 @@ #if !defined(BOOST_NO_CXX11_ALLOCATOR) #include +class type1 { + friend class std::allocator; + +public: + static unsigned int instances; + static const type1 object; + +protected: + explicit type1() { + instances++; + } + + type1(const type1&) { + instances++; + } + + ~type1() { + instances--; + } +}; + +unsigned int type1::instances; +const type1 type1::object; + template class creator { public: typedef T value_type; +#if defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + template + struct rebind { + typedef creator other; + }; +#endif + creator() { } @@ -44,109 +75,189 @@ public: } }; -class type { - friend class creator; +class type2 { + friend class creator; public: static unsigned int instances; - static type object; + static const type2 object; protected: - explicit type() { + explicit type2() { instances++; } - type(const type&) { + type2(const type2&) { instances++; } - ~type() { + ~type2() { instances--; } }; -unsigned int type::instances; -type type::object; +unsigned int type2::instances; +const type2 type2::object; int main() { - BOOST_TEST(type::instances == 1); + BOOST_TEST(type1::instances == 1); { - boost::shared_ptr a1 = boost::allocate_shared(creator(), 3); + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 3); BOOST_TEST(a1.use_count() == 1); BOOST_TEST(a1.get() != 0); - BOOST_TEST(type::instances == 4); + BOOST_TEST(type1::instances == 4); a1.reset(); - BOOST_TEST(type::instances == 1); + BOOST_TEST(type1::instances == 1); } - BOOST_TEST(type::instances == 1); + BOOST_TEST(type1::instances == 1); { - boost::shared_ptr a1 = boost::allocate_shared(creator()); + boost::shared_ptr a1 = boost::allocate_shared(std::allocator()); BOOST_TEST(a1.use_count() == 1); BOOST_TEST(a1.get() != 0); - BOOST_TEST(type::instances == 4); + BOOST_TEST(type1::instances == 4); a1.reset(); - BOOST_TEST(type::instances == 1); + BOOST_TEST(type1::instances == 1); } - BOOST_TEST(type::instances == 1); + BOOST_TEST(type1::instances == 1); { - boost::shared_ptr a1 = boost::allocate_shared(creator(), 2); + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2); BOOST_TEST(a1.get() != 0); BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type::instances == 5); + BOOST_TEST(type1::instances == 5); a1.reset(); - BOOST_TEST(type::instances == 1); + BOOST_TEST(type1::instances == 1); } - BOOST_TEST(type::instances == 1); + BOOST_TEST(type1::instances == 1); { - boost::shared_ptr a1 = boost::allocate_shared(creator()); + boost::shared_ptr a1 = boost::allocate_shared(std::allocator()); BOOST_TEST(a1.get() != 0); BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type::instances == 5); + BOOST_TEST(type1::instances == 5); a1.reset(); - BOOST_TEST(type::instances == 1); + BOOST_TEST(type1::instances == 1); } - BOOST_TEST(type::instances == 1); + BOOST_TEST(type1::instances == 1); { - boost::shared_ptr a1 = boost::allocate_shared(creator(), 3); + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 3); BOOST_TEST(a1.get() != 0); BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type::instances == 4); + BOOST_TEST(type1::instances == 4); a1.reset(); - BOOST_TEST(type::instances == 1); + BOOST_TEST(type1::instances == 1); } - BOOST_TEST(type::instances == 1); + BOOST_TEST(type1::instances == 1); { - boost::shared_ptr a1 = boost::allocate_shared(creator()); + boost::shared_ptr a1 = boost::allocate_shared(std::allocator()); BOOST_TEST(a1.get() != 0); BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type::instances == 4); + BOOST_TEST(type1::instances == 4); a1.reset(); - BOOST_TEST(type::instances == 1); + BOOST_TEST(type1::instances == 1); } - BOOST_TEST(type::instances == 1); + BOOST_TEST(type1::instances == 1); { - boost::shared_ptr a1 = boost::allocate_shared(creator(), 2); + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2); BOOST_TEST(a1.get() != 0); BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type::instances == 5); + BOOST_TEST(type1::instances == 5); a1.reset(); - BOOST_TEST(type::instances == 1); + BOOST_TEST(type1::instances == 1); } - BOOST_TEST(type::instances == 1); + BOOST_TEST(type1::instances == 1); { - boost::shared_ptr a1 = boost::allocate_shared(creator()); + boost::shared_ptr a1 = boost::allocate_shared(std::allocator()); BOOST_TEST(a1.get() != 0); BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type::instances == 5); + BOOST_TEST(type1::instances == 5); a1.reset(); - BOOST_TEST(type::instances == 1); + BOOST_TEST(type1::instances == 1); + } + + BOOST_TEST(type2::instances == 1); + { + boost::shared_ptr a1 = boost::allocate_shared(creator(), 3); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(type2::instances == 4); + a1.reset(); + BOOST_TEST(type2::instances == 1); + } + + BOOST_TEST(type2::instances == 1); + { + boost::shared_ptr a1 = boost::allocate_shared(creator()); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(type2::instances == 4); + a1.reset(); + BOOST_TEST(type2::instances == 1); + } + + BOOST_TEST(type2::instances == 1); + { + boost::shared_ptr a1 = boost::allocate_shared(creator(), 2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type2::instances == 5); + a1.reset(); + BOOST_TEST(type2::instances == 1); + } + + BOOST_TEST(type2::instances == 1); + { + boost::shared_ptr a1 = boost::allocate_shared(creator()); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type2::instances == 5); + a1.reset(); + BOOST_TEST(type2::instances == 1); + } + + BOOST_TEST(type2::instances == 1); + { + boost::shared_ptr a1 = boost::allocate_shared(creator(), 3); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type2::instances == 4); + a1.reset(); + BOOST_TEST(type2::instances == 1); + } + + BOOST_TEST(type2::instances == 1); + { + boost::shared_ptr a1 = boost::allocate_shared(creator()); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type2::instances == 4); + a1.reset(); + BOOST_TEST(type2::instances == 1); + } + + BOOST_TEST(type2::instances == 1); + { + boost::shared_ptr a1 = boost::allocate_shared(creator(), 2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type2::instances == 5); + a1.reset(); + BOOST_TEST(type2::instances == 1); + } + + BOOST_TEST(type2::instances == 1); + { + boost::shared_ptr a1 = boost::allocate_shared(creator()); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type2::instances == 5); + a1.reset(); + BOOST_TEST(type2::instances == 1); } return boost::report_errors(); From 5008957bd0af370384d99a86c8f26789ba2afd61 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Wed, 5 Feb 2014 09:10:45 -0800 Subject: [PATCH 33/39] Remove type2 tests in a_s_construct_test --- test/allocate_shared_array_construct_test.cpp | 184 ++++-------------- 1 file changed, 40 insertions(+), 144 deletions(-) diff --git a/test/allocate_shared_array_construct_test.cpp b/test/allocate_shared_array_construct_test.cpp index 6501fa0..66acd0d 100644 --- a/test/allocate_shared_array_construct_test.cpp +++ b/test/allocate_shared_array_construct_test.cpp @@ -10,30 +10,6 @@ #if !defined(BOOST_NO_CXX11_ALLOCATOR) #include -class type1 { - friend class std::allocator; - -public: - static unsigned int instances; - static const type1 object; - -protected: - explicit type1() { - instances++; - } - - type1(const type1&) { - instances++; - } - - ~type1() { - instances--; - } -}; - -unsigned int type1::instances; -const type1 type1::object; - template class creator { public: @@ -75,189 +51,109 @@ public: } }; -class type2 { - friend class creator; +class type { + friend class creator; public: static unsigned int instances; - static const type2 object; + static const type object; protected: - explicit type2() { + explicit type() { instances++; } - type2(const type2&) { + type(const type&) { instances++; } - ~type2() { + ~type() { instances--; } }; -unsigned int type2::instances; -const type2 type2::object; +unsigned int type::instances; +const type type::object; int main() { - BOOST_TEST(type1::instances == 1); + BOOST_TEST(type::instances == 1); { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 3); + boost::shared_ptr a1 = boost::allocate_shared(creator(), 3); BOOST_TEST(a1.use_count() == 1); BOOST_TEST(a1.get() != 0); - BOOST_TEST(type1::instances == 4); + BOOST_TEST(type::instances == 4); a1.reset(); - BOOST_TEST(type1::instances == 1); + BOOST_TEST(type::instances == 1); } - BOOST_TEST(type1::instances == 1); + BOOST_TEST(type::instances == 1); { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator()); + boost::shared_ptr a1 = boost::allocate_shared(creator()); BOOST_TEST(a1.use_count() == 1); BOOST_TEST(a1.get() != 0); - BOOST_TEST(type1::instances == 4); + BOOST_TEST(type::instances == 4); a1.reset(); - BOOST_TEST(type1::instances == 1); + BOOST_TEST(type::instances == 1); } - BOOST_TEST(type1::instances == 1); + BOOST_TEST(type::instances == 1); { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2); + boost::shared_ptr a1 = boost::allocate_shared(creator(), 2); BOOST_TEST(a1.get() != 0); BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type1::instances == 5); + BOOST_TEST(type::instances == 5); a1.reset(); - BOOST_TEST(type1::instances == 1); + BOOST_TEST(type::instances == 1); } - BOOST_TEST(type1::instances == 1); + BOOST_TEST(type::instances == 1); { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator()); + boost::shared_ptr a1 = boost::allocate_shared(creator()); BOOST_TEST(a1.get() != 0); BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type1::instances == 5); + BOOST_TEST(type::instances == 5); a1.reset(); - BOOST_TEST(type1::instances == 1); + BOOST_TEST(type::instances == 1); } - BOOST_TEST(type1::instances == 1); + BOOST_TEST(type::instances == 1); { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 3); + boost::shared_ptr a1 = boost::allocate_shared(creator(), 3); BOOST_TEST(a1.get() != 0); BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type1::instances == 4); + BOOST_TEST(type::instances == 4); a1.reset(); - BOOST_TEST(type1::instances == 1); + BOOST_TEST(type::instances == 1); } - BOOST_TEST(type1::instances == 1); + BOOST_TEST(type::instances == 1); { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator()); + boost::shared_ptr a1 = boost::allocate_shared(creator()); BOOST_TEST(a1.get() != 0); BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type1::instances == 4); + BOOST_TEST(type::instances == 4); a1.reset(); - BOOST_TEST(type1::instances == 1); + BOOST_TEST(type::instances == 1); } - BOOST_TEST(type1::instances == 1); + BOOST_TEST(type::instances == 1); { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 2); + boost::shared_ptr a1 = boost::allocate_shared(creator(), 2); BOOST_TEST(a1.get() != 0); BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type1::instances == 5); + BOOST_TEST(type::instances == 5); a1.reset(); - BOOST_TEST(type1::instances == 1); + BOOST_TEST(type::instances == 1); } - BOOST_TEST(type1::instances == 1); + BOOST_TEST(type::instances == 1); { - boost::shared_ptr a1 = boost::allocate_shared(std::allocator()); + boost::shared_ptr a1 = boost::allocate_shared(creator()); BOOST_TEST(a1.get() != 0); BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type1::instances == 5); + BOOST_TEST(type::instances == 5); a1.reset(); - BOOST_TEST(type1::instances == 1); - } - - BOOST_TEST(type2::instances == 1); - { - boost::shared_ptr a1 = boost::allocate_shared(creator(), 3); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(type2::instances == 4); - a1.reset(); - BOOST_TEST(type2::instances == 1); - } - - BOOST_TEST(type2::instances == 1); - { - boost::shared_ptr a1 = boost::allocate_shared(creator()); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(type2::instances == 4); - a1.reset(); - BOOST_TEST(type2::instances == 1); - } - - BOOST_TEST(type2::instances == 1); - { - boost::shared_ptr a1 = boost::allocate_shared(creator(), 2); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type2::instances == 5); - a1.reset(); - BOOST_TEST(type2::instances == 1); - } - - BOOST_TEST(type2::instances == 1); - { - boost::shared_ptr a1 = boost::allocate_shared(creator()); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type2::instances == 5); - a1.reset(); - BOOST_TEST(type2::instances == 1); - } - - BOOST_TEST(type2::instances == 1); - { - boost::shared_ptr a1 = boost::allocate_shared(creator(), 3); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type2::instances == 4); - a1.reset(); - BOOST_TEST(type2::instances == 1); - } - - BOOST_TEST(type2::instances == 1); - { - boost::shared_ptr a1 = boost::allocate_shared(creator()); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type2::instances == 4); - a1.reset(); - BOOST_TEST(type2::instances == 1); - } - - BOOST_TEST(type2::instances == 1); - { - boost::shared_ptr a1 = boost::allocate_shared(creator(), 2); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type2::instances == 5); - a1.reset(); - BOOST_TEST(type2::instances == 1); - } - - BOOST_TEST(type2::instances == 1); - { - boost::shared_ptr a1 = boost::allocate_shared(creator()); - BOOST_TEST(a1.get() != 0); - BOOST_TEST(a1.use_count() == 1); - BOOST_TEST(type2::instances == 5); - a1.reset(); - BOOST_TEST(type2::instances == 1); + BOOST_TEST(type::instances == 1); } return boost::report_errors(); From d46e3c7cbdf831eb95318b51f4f55e73654ffd0a Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Thu, 6 Feb 2014 01:38:58 -0800 Subject: [PATCH 34/39] Simplify/tidy array_allocator and array_deleter --- .../smart_ptr/detail/array_allocator.hpp | 69 +++++++++++-------- .../boost/smart_ptr/detail/array_deleter.hpp | 62 ++++++++--------- 2 files changed, 69 insertions(+), 62 deletions(-) diff --git a/include/boost/smart_ptr/detail/array_allocator.hpp b/include/boost/smart_ptr/detail/array_allocator.hpp index f085523..68170e9 100644 --- a/include/boost/smart_ptr/detail/array_allocator.hpp +++ b/include/boost/smart_ptr/detail/array_allocator.hpp @@ -116,7 +116,7 @@ namespace boost { pointer allocate(size_type count, const void* value = 0) { std::size_t a1 = boost::alignment_of::value; - std::size_t n1 = count * sizeof(Y) + a1 - 1; + std::size_t n1 = count * sizeof(value_type) + a1 - 1; CA ca(pair); #if !defined(BOOST_NO_CXX11_ALLOCATOR) char* p1 = CT::allocate(ca, size + n1, value); @@ -133,7 +133,7 @@ namespace boost { void deallocate(pointer memory, size_type count) { std::size_t a1 = boost::alignment_of::value; - std::size_t n1 = count * sizeof(Y) + a1 - 1; + std::size_t n1 = count * sizeof(value_type) + a1 - 1; char* p1 = reinterpret_cast(memory); CA ca(pair); #if !defined(BOOST_NO_CXX11_ALLOCATOR) @@ -143,30 +143,34 @@ namespace boost { #endif } + template + void construct(U* memory, const_reference value) { #if !defined(BOOST_NO_CXX11_ALLOCATOR) -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \ - !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - template - void construct(U* memory, Args&&... args) { - YT::construct(pair, memory, std::forward(args)...); - } -#else - template - void construct(U* memory, const Y& value) { YT::construct(pair, memory, value); - } -#endif - template - void destroy(U* memory) { - YT::destroy(pair, memory); - } + #else - void construct(pointer memory, const Y& value) { pair.construct(memory, value); +#endif } - void destroy(pointer memory) { + template + void destroy(U* memory) { +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + YT::destroy(pair, memory); +#else pair.destroy(memory); +#endif + } + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \ + !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template + void construct(U* memory, Args&&... args) { +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + YT::construct(pair, memory, std::forward(args)...); +#else + pair.construct(memory, std::forward(args)...); +#endif } #endif @@ -213,13 +217,13 @@ namespace boost { ms_allocator(std::size_t size_, type** data_) : ms_allocator_base(size_), - data(data_) { + data(data_) { } template ms_allocator(const ms_allocator& other) : ms_allocator_base(other), - data(other.data) { + data(other.data) { } pointer address(reference value) const { @@ -236,9 +240,9 @@ namespace boost { pointer allocate(size_type count, const void* = 0) { std::size_t a1 = boost::alignment_of::value; - std::size_t n1 = count * sizeof(Y)+a1 - 1; + std::size_t n1 = count * sizeof(value_type) + a1 - 1; void* p1 = ::operator new(n1 + size); - char* p2 = static_cast(p1)+n1; + char* p2 = static_cast(p1) + n1; while (std::size_t(p2) % a1 != 0) { p2--; } @@ -251,15 +255,26 @@ namespace boost { ::operator delete(p1); } - void construct(pointer memory, const Y& value) { + template + void construct(U* memory, const_reference value) { void* p1 = memory; - ::new(p1) Y(value); + ::new(p1) U(value); } - void destroy(pointer memory) { - memory->~Y(); + template + void destroy(U* memory) { + memory->~U(); } +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \ + !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template + void construct(U* memory, Args&&... args) { + void* p1 = memory; + ::new(p1) U(std::forward(args)...); + } +#endif + template bool operator==(const ms_allocator&) const { return true; diff --git a/include/boost/smart_ptr/detail/array_deleter.hpp b/include/boost/smart_ptr/detail/array_deleter.hpp index bf967a0..adaac18 100644 --- a/include/boost/smart_ptr/detail/array_deleter.hpp +++ b/include/boost/smart_ptr/detail/array_deleter.hpp @@ -87,11 +87,8 @@ namespace boost { typedef std::allocator_traits TT; #endif - void destroy(type*, std::size_t, boost::true_type) { - } - - void destroy(type* memory, std::size_t n, boost::false_type) { - for (std::size_t i = n; i > 0;) { + void destroy(type* memory, std::size_t count) { + for (std::size_t i = count; i > 0;) { #if !defined(BOOST_NO_CXX11_ALLOCATOR) TT::destroy(pair, &memory[--i]); #else @@ -100,11 +97,6 @@ namespace boost { } } - void destroy(type* memory, std::size_t n) { - boost::has_trivial_destructor tag; - destroy(memory, n, tag); - } - void value_init(type* memory, boost::true_type) { for (std::size_t i = 0; i < size; i++) { #if !defined(BOOST_NO_CXX11_ALLOCATOR) @@ -224,15 +216,15 @@ namespace boost { void destroy(type*, std::size_t, boost::true_type) { } - void destroy(type* memory, std::size_t n, boost::false_type) { - for (std::size_t i = n; i > 0;) { + void destroy(type* memory, std::size_t count, boost::false_type) { + for (std::size_t i = count; i > 0;) { memory[--i].~type(); } } - void destroy(type* memory, std::size_t n) { + void destroy(type* memory, std::size_t count) { boost::has_trivial_destructor tag; - destroy(memory, n, tag); + destroy(memory, count, tag); } void value_init(type* memory, boost::true_type) { @@ -267,6 +259,27 @@ namespace boost { value_init(memory, tag); } + template + void value_init(type* memory, const type* list) { +#if !defined(BOOST_NO_EXCEPTIONS) + std::size_t i = 0; + try { + for (; i < size; i++) { + void* p1 = memory + i; + ::new(p1) type(list[i % N]); + } + } catch (...) { + destroy(memory, i); + throw; + } +#else + for (std::size_t i = 0; i < size; i++) { + void* p1 = memory + i; + ::new(p1) type(list[i % N]); + } +#endif + } + void default_init(type*, boost::true_type) { } @@ -295,27 +308,6 @@ namespace boost { default_init(memory, tag); } - template - void value_init(type* memory, const type* list) { -#if !defined(BOOST_NO_EXCEPTIONS) - std::size_t i = 0; - try { - for (; i < size; i++) { - void* p1 = memory + i; - ::new(p1) type(list[i % N]); - } - } catch (...) { - destroy(memory, i); - throw; - } -#else - for (std::size_t i = 0; i < size; i++) { - void* p1 = memory + i; - ::new(p1) type(list[i % N]); - } -#endif - } - type* object; }; } From 52a5c422a15b3bfa95e528844f46de638eb11732 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Thu, 6 Feb 2014 01:40:46 -0800 Subject: [PATCH 35/39] Correct typo in shared_array documentation --- shared_array.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared_array.htm b/shared_array.htm index 4c31458..8fa5a7f 100644 --- a/shared_array.htm +++ b/shared_array.htm @@ -174,7 +174,7 @@ template<class T>

Equivalent to a.swap(b). Matches the interface of std::swap. Provided as an aid to generic programming.


-

$Date

+

$Date$

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version 1.0. See accompanying file LICENSE_1_0.txt or From e1f170cd494d2e7ce5e6e7d3f0fe016aceb88048 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Thu, 6 Feb 2014 17:09:27 -0800 Subject: [PATCH 36/39] Drop variadic templates in unit test for VC11 --- test/allocate_shared_array_construct_test.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/allocate_shared_array_construct_test.cpp b/test/allocate_shared_array_construct_test.cpp index 66acd0d..ee1c812 100644 --- a/test/allocate_shared_array_construct_test.cpp +++ b/test/allocate_shared_array_construct_test.cpp @@ -39,10 +39,10 @@ public: ::operator delete(p1); } - template - void construct(U* memory, Args&&... args) { + template + void construct(U* memory) { void* p1 = memory; - ::new(p1) U(std::forward(args)...); + ::new(p1) U(); } template From a64cc5c41c6bd0911f4ce8e926610f0ed000b1d7 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 7 Feb 2014 17:37:00 +0200 Subject: [PATCH 37/39] Use allocator)traits<>::destroy in sp_counted_impl_pda::destroy --- include/boost/smart_ptr/detail/sp_counted_impl.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/boost/smart_ptr/detail/sp_counted_impl.hpp b/include/boost/smart_ptr/detail/sp_counted_impl.hpp index 8702532..a7b43ae 100644 --- a/include/boost/smart_ptr/detail/sp_counted_impl.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_impl.hpp @@ -236,7 +236,16 @@ public: A2 a2( a_ ); +#if !defined( BOOST_NO_CXX11_ALLOCATOR ) + + std::allocator_traits::destroy( a2, this ); + +#else + this->~this_type(); + +#endif + a2.deallocate( this, 1 ); } From c23bd41c4402b31f61ce29a59129fddc0085db45 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Fri, 7 Feb 2014 08:03:47 -0800 Subject: [PATCH 38/39] Refactor make_shared for arrays Refactor implementation to later simplify making an optimization [for the C++11 allocator case] for when sp_counted_impl_pda destruction invokes the allocator's destroy function instead of the type's destructor. --- .../boost/smart_ptr/allocate_shared_array.hpp | 74 +++--- .../{as_pair.hpp => allocator_pair.hpp} | 10 +- .../smart_ptr/detail/array_allocator.hpp | 39 ++- .../boost/smart_ptr/detail/array_deleter.hpp | 245 ++--------------- .../boost/smart_ptr/detail/array_utility.hpp | 251 ++++++++++++++++++ include/boost/smart_ptr/make_shared_array.hpp | 64 +++-- 6 files changed, 375 insertions(+), 308 deletions(-) rename include/boost/smart_ptr/detail/{as_pair.hpp => allocator_pair.hpp} (62%) create mode 100644 include/boost/smart_ptr/detail/array_utility.hpp diff --git a/include/boost/smart_ptr/allocate_shared_array.hpp b/include/boost/smart_ptr/allocate_shared_array.hpp index c35a106..a27b99f 100644 --- a/include/boost/smart_ptr/allocate_shared_array.hpp +++ b/include/boost/smart_ptr/allocate_shared_array.hpp @@ -21,16 +21,18 @@ namespace boost { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; typedef typename boost::remove_cv::type T3; + typedef boost::detail::as_allocator A1; + typedef boost::detail::as_deleter D1; T1* p1 = 0; T3* p2 = 0; std::size_t n1 = size * boost::detail::array_total::size; - boost::detail::as_allocator a1(allocator, n1, &p2); - boost::detail::as_deleter d1(allocator, n1); + D1 d1(allocator, n1); + A1 a1(allocator, n1, &p2); boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::as_deleter* D2; p1 = reinterpret_cast(p2); - D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->init(p2); + boost::detail::as_init(allocator, p2, n1); + D1* d2 = static_cast(s1._internal_get_untyped_deleter()); + d2->set(p2); return boost::shared_ptr(s1, p1); } @@ -43,15 +45,17 @@ namespace boost { enum { N = boost::detail::array_total::size }; + typedef boost::detail::as_allocator A1; + typedef boost::detail::as_deleter D1; T1* p1 = 0; T3* p2 = 0; - boost::detail::as_allocator a1(allocator, &p2); - boost::detail::as_deleter d1(allocator); + D1 d1(allocator); + A1 a1(allocator, &p2); boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::as_deleter* D2; p1 = reinterpret_cast(p2); - D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->init(p2); + boost::detail::as_init(allocator, p2, N); + D1* d2 = static_cast(s1._internal_get_untyped_deleter()); + d2->set(p2); return boost::shared_ptr(s1, p1); } @@ -63,6 +67,8 @@ namespace boost { typedef typename boost::detail::array_base::type T2; typedef typename boost::remove_cv::type T3; typedef const T2 T4; + typedef boost::detail::as_allocator A1; + typedef boost::detail::as_deleter D1; enum { M = boost::detail::array_total::size }; @@ -70,13 +76,13 @@ namespace boost { T3* p2 = 0; T4* p3 = reinterpret_cast(&value); std::size_t n1 = M * size; - boost::detail::as_allocator a1(allocator, n1, &p2); - boost::detail::as_deleter d1(allocator, n1); + D1 d1(allocator, n1); + A1 a1(allocator, n1, &p2); boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::as_deleter* D2; p1 = reinterpret_cast(p2); - D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->template init(p2, p3); + boost::detail::as_init(allocator, p2, n1, p3); + D1* d2 = static_cast(s1._internal_get_untyped_deleter()); + d2->set(p2); return boost::shared_ptr(s1, p1); } @@ -90,18 +96,20 @@ namespace boost { typedef const T2 T4; enum { M = boost::detail::array_total::size, - N = boost::detail::array_total::size + N = boost::detail::array_total::size }; + typedef boost::detail::as_allocator A1; + typedef boost::detail::as_deleter D1; T1* p1 = 0; T3* p2 = 0; T4* p3 = reinterpret_cast(&value); - boost::detail::as_allocator a1(allocator, &p2); - boost::detail::as_deleter d1(allocator); + D1 d1(allocator); + A1 a1(allocator, &p2); boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::as_deleter* D2; p1 = reinterpret_cast(p2); - D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->template init(p2, p3); + boost::detail::as_init(allocator, p2, N, p3); + D1* d2 = static_cast(s1._internal_get_untyped_deleter()); + d2->set(p2); return boost::shared_ptr(s1, p1); } @@ -111,16 +119,18 @@ namespace boost { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; typedef typename boost::remove_cv::type T3; + typedef boost::detail::as_allocator A1; + typedef boost::detail::ms_deleter D1; T1* p1 = 0; T3* p2 = 0; std::size_t n1 = size * boost::detail::array_total::size; - boost::detail::as_allocator a1(allocator, n1, &p2); - boost::detail::ms_deleter d1(n1); + D1 d1(n1); + A1 a1(allocator, n1, &p2); boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::ms_deleter* D2; p1 = reinterpret_cast(p2); - D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->noinit(p2); + boost::detail::ms_noinit(p2, n1); + D1* d2 = static_cast(s1._internal_get_untyped_deleter()); + d2->set(p2); return boost::shared_ptr(s1, p1); } @@ -133,15 +143,17 @@ namespace boost { enum { N = boost::detail::array_total::size }; + typedef boost::detail::as_allocator A1; + typedef boost::detail::ms_deleter D1; T1* p1 = 0; T3* p2 = 0; - boost::detail::as_allocator a1(allocator, &p2); - boost::detail::ms_deleter d1; + D1 d1; + A1 a1(allocator, &p2); boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::ms_deleter* D2; p1 = reinterpret_cast(p2); - D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->noinit(p2); + boost::detail::ms_noinit(p2, N); + D1* d2 = static_cast(s1._internal_get_untyped_deleter()); + d2->set(p2); return boost::shared_ptr(s1, p1); } } diff --git a/include/boost/smart_ptr/detail/as_pair.hpp b/include/boost/smart_ptr/detail/allocator_pair.hpp similarity index 62% rename from include/boost/smart_ptr/detail/as_pair.hpp rename to include/boost/smart_ptr/detail/allocator_pair.hpp index 829adc0..8910c90 100644 --- a/include/boost/smart_ptr/detail/as_pair.hpp +++ b/include/boost/smart_ptr/detail/allocator_pair.hpp @@ -1,13 +1,13 @@ /* - * Copyright (c) 2014 Glen Joseph Fernandes + * Copyright (c) 2014 Glen Joseph Fernandes * glenfe at live dot com * - * Distributed under the Boost Software License, - * Version 1.0. (See accompanying file LICENSE_1_0.txt + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt * or copy at http://boost.org/LICENSE_1_0.txt) */ -#ifndef BOOST_SMART_PTR_DETAIL_AS_PAIR_HPP -#define BOOST_SMART_PTR_DETAIL_AS_PAIR_HPP +#ifndef BOOST_SMART_PTR_DETAIL_ALLOCATOR_PAIR_HPP +#define BOOST_SMART_PTR_DETAIL_ALLOCATOR_PAIR_HPP #include diff --git a/include/boost/smart_ptr/detail/array_allocator.hpp b/include/boost/smart_ptr/detail/array_allocator.hpp index 68170e9..cca57b7 100644 --- a/include/boost/smart_ptr/detail/array_allocator.hpp +++ b/include/boost/smart_ptr/detail/array_allocator.hpp @@ -9,10 +9,10 @@ #ifndef BOOST_SMART_PTR_DETAIL_ARRAY_ALLOCATOR_HPP #define BOOST_SMART_PTR_DETAIL_ARRAY_ALLOCATOR_HPP +#include #include -#include #include -#if !defined(BOOST_NO_CXX11_ALLOCATOR) +#if !defined(BOOST_NO_CXX11_ALLOCATOR) #include #endif @@ -45,22 +45,20 @@ namespace boost { template friend class as_allocator; -#if !defined(BOOST_NO_CXX11_ALLOCATOR) && \ - !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) +#if !defined(BOOST_NO_CXX11_ALLOCATOR) typedef typename std::allocator_traits:: template rebind_alloc YA; typedef typename std::allocator_traits:: template rebind_alloc CA; + typedef typename std::allocator_traits:: + template rebind_traits YT; + typedef typename std::allocator_traits:: + template rebind_traits CT; #else typedef typename A::template rebind::other YA; typedef typename A::template rebind::other CA; #endif -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - typedef std::allocator_traits YT; - typedef std::allocator_traits CT; -#endif - public: typedef typename array_inner::type type; @@ -128,7 +126,7 @@ namespace boost { p2--; } *pair.data = reinterpret_cast(p2); - return reinterpret_cast(p1); + return reinterpret_cast(p1); } void deallocate(pointer memory, size_type count) { @@ -162,15 +160,12 @@ namespace boost { #endif } -#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \ - !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#if !defined(BOOST_NO_CXX11_ALLOCATOR) && \ + !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \ + !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) template void construct(U* memory, Args&&... args) { -#if !defined(BOOST_NO_CXX11_ALLOCATOR) YT::construct(pair, memory, std::forward(args)...); -#else - pair.construct(memory, std::forward(args)...); -#endif } #endif @@ -235,7 +230,10 @@ namespace boost { } size_type max_size() const { - return static_cast(-1) / sizeof(Y); + enum { + N = static_cast(-1) / sizeof(value_type) + }; + return N; } pointer allocate(size_type count, const void* = 0) { @@ -247,7 +245,7 @@ namespace boost { p2--; } *data = reinterpret_cast(p2); - return reinterpret_cast(p1); + return reinterpret_cast(p1); } void deallocate(pointer memory, size_type) { @@ -266,8 +264,9 @@ namespace boost { memory->~U(); } -#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \ - !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#if !defined(BOOST_NO_CXX11_ALLOCATOR) && \ + !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \ + !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) template void construct(U* memory, Args&&... args) { void* p1 = memory; diff --git a/include/boost/smart_ptr/detail/array_deleter.hpp b/include/boost/smart_ptr/detail/array_deleter.hpp index adaac18..ca320dc 100644 --- a/include/boost/smart_ptr/detail/array_deleter.hpp +++ b/include/boost/smart_ptr/detail/array_deleter.hpp @@ -9,14 +9,9 @@ #ifndef BOOST_SMART_PTR_DETAIL_ARRAY_DELETER_HPP #define BOOST_SMART_PTR_DETAIL_ARRAY_DELETER_HPP -#include +#include #include -#include -#include -#include -#if !defined(BOOST_NO_CXX11_ALLOCATOR) -#include -#endif +#include namespace boost { namespace detail { @@ -47,130 +42,35 @@ namespace boost { public: typedef typename array_inner::type type; - as_deleter(const A& allocator) - : pair(allocator, 0) { +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + typedef typename std::allocator_traits:: + template rebind_alloc allocator; +#else + typedef typename A:: + template rebind::other allocator; +#endif + + as_deleter(const A& allocator_) + : pair(allocator_, 0) { } - as_deleter(const A& allocator, std::size_t size_) + as_deleter(const A& allocator_, std::size_t size_) : ms_deleter_base(size_), - pair(allocator, 0) { + pair(allocator_, 0) { } - void init(type* memory) { - value_init(memory); - pair.data = memory; - } - - template - void init(type* memory, const type* value) { - value_init(memory, value); + void set(type* memory) { pair.data = memory; } void operator()(const void*) { if (pair.data) { - destroy(pair.data, size); + as_destroy(pair, pair.data, size); } } private: -#if !defined(BOOST_NO_CXX11_ALLOCATOR) && \ - !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) - typedef typename std::allocator_traits:: - template rebind_alloc TA; -#else - typedef typename A:: - template rebind::other TA; -#endif - -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - typedef std::allocator_traits TT; -#endif - - void destroy(type* memory, std::size_t count) { - for (std::size_t i = count; i > 0;) { -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - TT::destroy(pair, &memory[--i]); -#else - memory[--i].~type(); -#endif - } - } - - void value_init(type* memory, boost::true_type) { - for (std::size_t i = 0; i < size; i++) { -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - TT::construct(pair, memory + i); -#else - void* p1 = memory + i; - ::new(p1) type(); -#endif - } - } - - void value_init(type* memory, boost::false_type) { -#if !defined(BOOST_NO_EXCEPTIONS) - std::size_t i = 0; - try { - for (; i < size; i++) { -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - TT::construct(pair, memory + i); -#else - void* p1 = memory + i; - ::new(p1) type(); -#endif - } - } catch (...) { - destroy(memory, i); - throw; - } -#else - for (std::size_t i = 0; i < size; i++) { -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - TT::construct(pair, memory + i); -#else - void* p1 = memory + i; - ::new(p1) type(); -#endif - } -#endif - } - - void value_init(type* memory) { - boost::has_trivial_default_constructor tag; - value_init(memory, tag); - } - - template - void value_init(type* memory, const type* list) { -#if !defined(BOOST_NO_EXCEPTIONS) - std::size_t i = 0; - try { - for (; i < size; i++) { -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - TT::construct(pair, memory + i, list[i % N]); -#else - void* p1 = memory + i; - ::new(p1) type(list[i % N]); -#endif - } - } catch (...) { - destroy(memory, i); - throw; - } -#else - for (std::size_t i = 0; i < size; i++) { -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - TT::construct(allocator, memory + i, list[i % N]); -#else - void* p1 = memory + i; - ::new(p1) type(list[i % N]); -#endif - } -#endif - } - - as_pair pair; + as_pair pair; }; template @@ -190,124 +90,17 @@ namespace boost { object(0) { } - void init(type* memory) { - value_init(memory); - object = memory; - } - - template - void init(type* memory, const type* value) { - value_init(memory, value); - object = memory; - } - - void noinit(type* memory) { - default_init(memory); + void set(type* memory) { object = memory; } void operator()(const void*) { if (object) { - destroy(object, size); + ms_destroy(object, size); } } private: - void destroy(type*, std::size_t, boost::true_type) { - } - - void destroy(type* memory, std::size_t count, boost::false_type) { - for (std::size_t i = count; i > 0;) { - memory[--i].~type(); - } - } - - void destroy(type* memory, std::size_t count) { - boost::has_trivial_destructor tag; - destroy(memory, count, tag); - } - - void value_init(type* memory, boost::true_type) { - for (std::size_t i = 0; i < size; i++) { - void* p1 = memory + i; - ::new(p1) type(); - } - } - - void value_init(type* memory, boost::false_type) { -#if !defined(BOOST_NO_EXCEPTIONS) - std::size_t i = 0; - try { - for (; i < size; i++) { - void* p1 = memory + i; - ::new(p1) type(); - } - } catch (...) { - destroy(memory, i); - throw; - } -#else - for (std::size_t i = 0; i < size; i++) { - void* p1 = memory + i; - ::new(p1) type(); - } -#endif - } - - void value_init(type* memory) { - boost::has_trivial_default_constructor tag; - value_init(memory, tag); - } - - template - void value_init(type* memory, const type* list) { -#if !defined(BOOST_NO_EXCEPTIONS) - std::size_t i = 0; - try { - for (; i < size; i++) { - void* p1 = memory + i; - ::new(p1) type(list[i % N]); - } - } catch (...) { - destroy(memory, i); - throw; - } -#else - for (std::size_t i = 0; i < size; i++) { - void* p1 = memory + i; - ::new(p1) type(list[i % N]); - } -#endif - } - - void default_init(type*, boost::true_type) { - } - - void default_init(type* memory, boost::false_type) { -#if !defined(BOOST_NO_EXCEPTIONS) - std::size_t i = 0; - try { - for (; i < size; i++) { - void* p1 = memory + i; - ::new(p1) type; - } - } catch (...) { - destroy(memory, i); - throw; - } -#else - for (std::size_t i = 0; i < size; i++) { - void* p1 = memory + i; - ::new(p1) type; - } -#endif - } - - void default_init(type* memory) { - boost::has_trivial_default_constructor tag; - default_init(memory, tag); - } - type* object; }; } diff --git a/include/boost/smart_ptr/detail/array_utility.hpp b/include/boost/smart_ptr/detail/array_utility.hpp new file mode 100644 index 0000000..e4b690c --- /dev/null +++ b/include/boost/smart_ptr/detail/array_utility.hpp @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2012-2014 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#ifndef BOOST_SMART_PTR_DETAIL_ARRAY_UTILITY_HPP +#define BOOST_SMART_PTR_DETAIL_ARRAY_UTILITY_HPP + +#include +#include +#include +#if !defined(BOOST_NO_CXX11_ALLOCATOR) +#include +#endif + +namespace boost { + namespace detail { + typedef boost::true_type ms_is_trivial; + typedef boost::false_type ms_no_trivial; + + template + inline void ms_destroy(T*, std::size_t, ms_is_trivial) { + } + + template + inline void ms_destroy(T* memory, std::size_t size, ms_no_trivial) { + for (std::size_t i = size; i > 0;) { + memory[--i].~T(); + } + } + + template + inline void ms_destroy(T* memory, std::size_t size) { + boost::has_trivial_destructor trivial; + ms_destroy(memory, size, trivial); + } + +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + template + inline void as_destroy(A& allocator, T* memory, + std::size_t size) { + typedef typename std::allocator_traits:: + template rebind_traits TT; + for (std::size_t i = size; i > 0;) { + TT::destroy(allocator, &memory[--i]); + } + } +#else + template + inline void as_destroy(const A&, T* memory, + std::size_t size) { + boost::has_trivial_destructor trivial; + ms_destroy(memory, size, trivial); + } +#endif + + template + inline void ms_init(T* memory, std::size_t size, ms_is_trivial) { + for (std::size_t i = 0; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(); + } + } + + template + inline void ms_init(T* memory, std::size_t size, ms_no_trivial) { +#if !defined(BOOST_NO_EXCEPTIONS) + std::size_t i = 0; + try { + for (; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(); + } + } catch (...) { + ms_destroy(memory, i); + throw; + } +#else + for (std::size_t i = 0; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(); + } +#endif + } + + template + inline void ms_init(T* memory, std::size_t size) { + boost::has_trivial_default_constructor trivial; + ms_init(memory, size, trivial); + } + + +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + template + inline void as_init(const A& allocator, T* memory, std::size_t size, + ms_is_trivial) { + typedef typename std::allocator_traits:: + template rebind_alloc TA; + typedef typename std::allocator_traits:: + template rebind_traits TT; + TA a2(allocator); + for (std::size_t i = 0; i < size; i++) { + TT::construct(a2, memory + i); + } + } + + template + inline void as_init(const A& allocator, T* memory, std::size_t size, + ms_no_trivial) { + typedef typename std::allocator_traits:: + template rebind_alloc TA; + typedef typename std::allocator_traits:: + template rebind_traits TT; + TA a2(allocator); +#if !defined(BOOST_NO_EXCEPTIONS) + std::size_t i = 0; + try { + for (; i < size; i++) { + TT::construct(a2, memory + i); + } + } catch (...) { + as_destroy(a2, memory, i); + throw; + } +#else + for (std::size_t i = 0; i < size; i++) { + TT::construct(a2, memory + i); + } +#endif + } + + template + inline void as_init(const A& allocator, T* memory, std::size_t size) { + boost::has_trivial_default_constructor trivial; + as_init(allocator, memory, size, trivial); + } +#else + template + inline void as_init(const A&, T* memory, std::size_t size) { + boost::has_trivial_default_constructor trivial; + ms_init(memory, size, trivial); + } +#endif + + template + inline void ms_init(T* memory, std::size_t size, const T* list) { +#if !defined(BOOST_NO_EXCEPTIONS) + std::size_t i = 0; + try { + for (; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(list[i % N]); + } + } catch (...) { + ms_destroy(memory, i); + throw; + } +#else + for (std::size_t i = 0; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(list[i % N]); + } +#endif + } + +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + template + inline void as_init(const A& allocator, T* memory, std::size_t size, + const T* list) { + typedef typename std::allocator_traits:: + template rebind_alloc TA; + typedef typename std::allocator_traits:: + template rebind_traits TT; + TA a2(allocator); +#if !defined(BOOST_NO_EXCEPTIONS) + std::size_t i = 0; + try { + for (; i < size; i++) { + TT::construct(a2, memory + i, list[i % N]); + } + } catch (...) { + as_destroy(a2, memory, i); + throw; + } +#else + for (std::size_t i = 0; i < size; i++) { + TT::construct(a2, memory + i, list[i % N]); + } +#endif + } +#else + template + inline void as_init(const A&, T* memory, std::size_t size, + const T* list) { +#if !defined(BOOST_NO_EXCEPTIONS) + std::size_t i = 0; + try { + for (; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(list[i % N]); + } + } catch (...) { + ms_destroy(memory, i); + throw; + } +#else + for (std::size_t i = 0; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(list[i % N]); + } +#endif + } +#endif + + template + inline void ms_noinit(T*, std::size_t, ms_is_trivial) { + } + + template + inline void ms_noinit(T* memory, std::size_t size, ms_no_trivial) { +#if !defined(BOOST_NO_EXCEPTIONS) + std::size_t i = 0; + try { + for (; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T; + } + } catch (...) { + ms_destroy(memory, i); + throw; + } +#else + for (std::size_t i = 0; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T; + } +#endif + } + + template + inline void ms_noinit(T* memory, std::size_t size) { + boost::has_trivial_default_constructor trivial; + ms_noinit(memory, size, trivial); + } + } +} + +#endif diff --git a/include/boost/smart_ptr/make_shared_array.hpp b/include/boost/smart_ptr/make_shared_array.hpp index 2deba39..eb179ee 100644 --- a/include/boost/smart_ptr/make_shared_array.hpp +++ b/include/boost/smart_ptr/make_shared_array.hpp @@ -21,16 +21,18 @@ namespace boost { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; typedef typename boost::remove_cv::type T3; + typedef boost::detail::ms_allocator A1; + typedef boost::detail::ms_deleter D1; T1* p1 = 0; T3* p2 = 0; std::size_t n1 = size * boost::detail::array_total::size; + D1 d1(n1); boost::detail::ms_allocator a1(n1, &p2); - boost::detail::ms_deleter d1(n1); boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::ms_deleter* D2; p1 = reinterpret_cast(p2); - D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->init(p2); + boost::detail::ms_init(p2, n1); + D1* d2 = static_cast(s1._internal_get_untyped_deleter()); + d2->set(p2); return boost::shared_ptr(s1, p1); } @@ -43,15 +45,17 @@ namespace boost { enum { N = boost::detail::array_total::size }; + typedef boost::detail::ms_allocator A1; + typedef boost::detail::ms_deleter D1; T1* p1 = 0; T3* p2 = 0; + D1 d1; boost::detail::ms_allocator a1(&p2); - boost::detail::ms_deleter d1; boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::ms_deleter* D2; p1 = reinterpret_cast(p2); - D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->init(p2); + boost::detail::ms_init(p2, N); + D1* d2 = static_cast(s1._internal_get_untyped_deleter()); + d2->set(p2); return boost::shared_ptr(s1, p1); } @@ -63,6 +67,8 @@ namespace boost { typedef typename boost::detail::array_base::type T2; typedef typename boost::remove_cv::type T3; typedef const T2 T4; + typedef boost::detail::ms_allocator A1; + typedef boost::detail::ms_deleter D1; enum { M = boost::detail::array_total::size }; @@ -70,13 +76,13 @@ namespace boost { T3* p2 = 0; T4* p3 = reinterpret_cast(&value); std::size_t n1 = M * size; + D1 d1(n1); boost::detail::ms_allocator a1(n1, &p2); - boost::detail::ms_deleter d1(n1); boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::ms_deleter* D2; p1 = reinterpret_cast(p2); - D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->template init(p2, p3); + boost::detail::ms_init(p2, n1, p3); + D1* d2 = static_cast(s1._internal_get_untyped_deleter()); + d2->set(p2); return boost::shared_ptr(s1, p1); } @@ -91,16 +97,18 @@ namespace boost { M = boost::detail::array_total::size, N = boost::detail::array_total::size }; + typedef boost::detail::ms_allocator A1; + typedef boost::detail::ms_deleter D1; T1* p1 = 0; T3* p2 = 0; T4* p3 = reinterpret_cast(&value); + D1 d1; boost::detail::ms_allocator a1(&p2); - boost::detail::ms_deleter d1; boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::ms_deleter* D2; p1 = reinterpret_cast(p2); - D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->template init(p2, p3); + boost::detail::ms_init(p2, N, p3); + D1* d2 = static_cast(s1._internal_get_untyped_deleter()); + d2->set(p2); return boost::shared_ptr(s1, p1); } @@ -110,16 +118,18 @@ namespace boost { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; typedef typename boost::remove_cv::type T3; + typedef boost::detail::ms_allocator A1; + typedef boost::detail::ms_deleter D1; T1* p1 = 0; T3* p2 = 0; std::size_t n1 = size * boost::detail::array_total::size; - boost::detail::ms_allocator a1(n1, &p2); - boost::detail::ms_deleter d1(n1); + D1 d1(n1); + A1 a1(n1, &p2); boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::ms_deleter* D2; p1 = reinterpret_cast(p2); - D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->noinit(p2); + boost::detail::ms_noinit(p2, n1); + D1* d2 = static_cast(s1._internal_get_untyped_deleter()); + d2->set(p2); return boost::shared_ptr(s1, p1); } @@ -132,15 +142,17 @@ namespace boost { enum { N = boost::detail::array_total::size }; + typedef boost::detail::ms_allocator A1; + typedef boost::detail::ms_deleter D1; T1* p1 = 0; T3* p2 = 0; - boost::detail::ms_allocator a1(&p2); - boost::detail::ms_deleter d1; + D1 d1; + A1 a1(&p2); boost::shared_ptr s1(p1, d1, a1); - typedef boost::detail::ms_deleter* D2; p1 = reinterpret_cast(p2); - D2 d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->noinit(p2); + boost::detail::ms_noinit(p2, N); + D1* d2 = static_cast(s1._internal_get_untyped_deleter()); + d2->set(p2); return boost::shared_ptr(s1, p1); } } From 54fb49a5be7ab6baea5906b5e5333daedd59adc6 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Sun, 9 Feb 2014 11:24:11 -0800 Subject: [PATCH 39/39] Use typedef A1 (warnings about unused typedefs) --- include/boost/smart_ptr/make_shared_array.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/smart_ptr/make_shared_array.hpp b/include/boost/smart_ptr/make_shared_array.hpp index eb179ee..50763d8 100644 --- a/include/boost/smart_ptr/make_shared_array.hpp +++ b/include/boost/smart_ptr/make_shared_array.hpp @@ -27,7 +27,7 @@ namespace boost { T3* p2 = 0; std::size_t n1 = size * boost::detail::array_total::size; D1 d1(n1); - boost::detail::ms_allocator a1(n1, &p2); + A1 a1(n1, &p2); boost::shared_ptr s1(p1, d1, a1); p1 = reinterpret_cast(p2); boost::detail::ms_init(p2, n1); @@ -50,7 +50,7 @@ namespace boost { T1* p1 = 0; T3* p2 = 0; D1 d1; - boost::detail::ms_allocator a1(&p2); + A1 a1(&p2); boost::shared_ptr s1(p1, d1, a1); p1 = reinterpret_cast(p2); boost::detail::ms_init(p2, N); @@ -77,7 +77,7 @@ namespace boost { T4* p3 = reinterpret_cast(&value); std::size_t n1 = M * size; D1 d1(n1); - boost::detail::ms_allocator a1(n1, &p2); + A1 a1(n1, &p2); boost::shared_ptr s1(p1, d1, a1); p1 = reinterpret_cast(p2); boost::detail::ms_init(p2, n1, p3); @@ -103,7 +103,7 @@ namespace boost { T3* p2 = 0; T4* p3 = reinterpret_cast(&value); D1 d1; - boost::detail::ms_allocator a1(&p2); + A1 a1(&p2); boost::shared_ptr s1(p1, d1, a1); p1 = reinterpret_cast(p2); boost::detail::ms_init(p2, N, p3);