fix doc example typo
[boost.git] / boost / signals2 / deconstruct.hpp
blob55541f38ec1de5bc217f450036f31729d38f54e4
1 #ifndef BOOST_SIGNALS2_DECONSTRUCT_HPP
2 #define BOOST_SIGNALS2_DECONSTRUCT_HPP
4 // deconstruct.hpp
5 //
6 // A factory function for creating a shared_ptr which creates
7 // an object and its owning shared_ptr with one allocation, similar
8 // to make_shared<T>(). It also supports postconstructors
9 // and predestructors through unqualified calls of adl_postconstruct() and
10 // adl_predestruct, relying on argument-dependent
11 // lookup to find the appropriate postconstructor or predestructor.
12 // Passing arguments to postconstructors is also supported.
14 // based on make_shared.hpp and make_shared_access patch from Michael Marcin
16 // Copyright (c) 2007, 2008 Peter Dimov
17 // Copyright (c) 2008 Michael Marcin
18 // Copyright (c) 2009 Frank Mori Hess
20 // Distributed under the Boost Software License, Version 1.0.
21 // See accompanying file LICENSE_1_0.txt or copy at
22 // http://www.boost.org/LICENSE_1_0.txt
24 // See http://www.boost.org
25 // for more information
27 #include <boost/config.hpp>
28 #include <boost/shared_ptr.hpp>
29 #include <boost/signals2/deconstruct_ptr.hpp>
30 #include <boost/type_traits/alignment_of.hpp>
31 #include <boost/type_traits/remove_const.hpp>
32 #include <boost/type_traits/type_with_alignment.hpp>
33 #include <cstddef>
34 #include <new>
36 namespace boost
38 template<typename T> class enable_shared_from_this;
40 namespace signals2
42 class deconstruct_access;
44 namespace detail
47 #if defined( BOOST_HAS_RVALUE_REFS )
48 template< class T > T&& forward( T &&t )
50 return t;
52 #endif
54 inline void adl_predestruct(...) {}
55 } // namespace detail
57 template<typename T>
58 class postconstructor_invoker
60 public:
61 operator const shared_ptr<T> & () const
63 return postconstruct();
65 const shared_ptr<T>& postconstruct() const
67 if(!_postconstructed)
69 adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()));
70 _postconstructed = true;
72 return _sp;
74 #if defined( BOOST_HAS_VARIADIC_TMPL ) && defined( BOOST_HAS_RVALUE_REFS )
75 template<class... Args>
76 const shared_ptr<T>& postconstruct(Args && ... args)
78 if(!_postconstructed)
80 adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()),
81 detail::forward<Args>(args)...);
82 _postconstructed = true;
84 return _sp;
86 #else
87 template<typename A1>
88 const shared_ptr<T>& postconstruct(const A1 &a1) const
90 if(!_postconstructed)
92 adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()),
93 a1);
94 _postconstructed = true;
96 return _sp;
98 template<typename A1, typename A2>
99 const shared_ptr<T>& postconstruct(const A1 &a1, const A2 &a2) const
101 if(!_postconstructed)
103 adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()),
104 a1, a2);
105 _postconstructed = true;
107 return _sp;
109 template<typename A1, typename A2, typename A3>
110 const shared_ptr<T>& postconstruct(const A1 &a1, const A2 &a2, const A3 &a3) const
112 if(!_postconstructed)
114 adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()),
115 a1, a2, a3);
116 _postconstructed = true;
118 return _sp;
120 template<typename A1, typename A2, typename A3, typename A4>
121 const shared_ptr<T>& postconstruct(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4) const
123 if(!_postconstructed)
125 adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()),
126 a1, a2, a3, a4);
127 _postconstructed = true;
129 return _sp;
131 template<typename A1, typename A2, typename A3, typename A4, typename A5>
132 const shared_ptr<T>& postconstruct(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5) const
134 if(!_postconstructed)
136 adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()),
137 a1, a2, a3, a4, a5);
138 _postconstructed = true;
140 return _sp;
142 template<typename A1, typename A2, typename A3, typename A4, typename A5,
143 typename A6>
144 const shared_ptr<T>& postconstruct(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5,
145 const A6 &a6) const
147 if(!_postconstructed)
149 adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()),
150 a1, a2, a3, a4, a5, a6);
151 _postconstructed = true;
153 return _sp;
155 template<typename A1, typename A2, typename A3, typename A4, typename A5,
156 typename A6, typename A7>
157 const shared_ptr<T>& postconstruct(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5,
158 const A6 &a6, const A7 &a7) const
160 if(!_postconstructed)
162 adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()),
163 a1, a2, a3, a4, a5, a6, a7);
164 _postconstructed = true;
166 return _sp;
168 template<typename A1, typename A2, typename A3, typename A4, typename A5,
169 typename A6, typename A7, typename A8>
170 const shared_ptr<T>& postconstruct(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5,
171 const A6 &a6, const A7 &a7, const A8 &a8) const
173 if(!_postconstructed)
175 adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()),
176 a1, a2, a3, a4, a5, a6, a7, a8);
177 _postconstructed = true;
179 return _sp;
181 template<typename A1, typename A2, typename A3, typename A4, typename A5,
182 typename A6, typename A7, typename A8, typename A9>
183 const shared_ptr<T>& postconstruct(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5,
184 const A6 &a6, const A7 &a7, const A8 &a8, const A9 &a9) const
186 if(!_postconstructed)
188 adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()),
189 a1, a2, a3, a4, a5, a6, a7, a8, a9);
190 _postconstructed = true;
192 return _sp;
194 #endif // else defined( BOOST_HAS_VARIADIC_TMPL ) && defined( BOOST_HAS_RVALUE_REFS )
195 private:
196 friend class boost::signals2::deconstruct_access;
197 postconstructor_invoker(const shared_ptr<T> & sp):
198 _sp(sp), _postconstructed(false)
200 shared_ptr<T> _sp;
201 mutable bool _postconstructed;
204 namespace detail
207 template< std::size_t N, std::size_t A > struct sp_aligned_storage
209 union type
211 char data_[ N ];
212 typename boost::type_with_alignment< A >::type align_;
216 template< class T > class deconstruct_deleter
218 private:
220 typedef typename sp_aligned_storage< sizeof( T ), ::boost::alignment_of< T >::value >::type storage_type;
222 bool initialized_;
223 storage_type storage_;
225 private:
227 void destroy()
229 if( initialized_ )
231 T* p = reinterpret_cast< T* >( storage_.data_ );
232 using boost::signals2::detail::adl_predestruct;
233 adl_predestruct(const_cast<typename boost::remove_const<T>::type *>(p));
234 p->~T();
235 initialized_ = false;
239 public:
241 deconstruct_deleter(): initialized_( false )
245 // this copy constructor is an optimization: we don't need to copy the storage_ member,
246 // and shouldn't be copying anyways after initialized_ becomes true
247 deconstruct_deleter(const deconstruct_deleter &): initialized_( false )
251 ~deconstruct_deleter()
253 destroy();
256 void operator()( T * )
258 destroy();
261 void * address()
263 return storage_.data_;
266 void set_initialized()
268 initialized_ = true;
271 } // namespace detail
273 class deconstruct_access
275 public:
277 template< class T >
278 static postconstructor_invoker<T> deconstruct()
280 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
282 detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
284 void * pv = pd->address();
286 new( pv ) T();
287 pd->set_initialized();
289 boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
290 boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
291 return retval;
295 #if defined( BOOST_HAS_VARIADIC_TMPL ) && defined( BOOST_HAS_RVALUE_REFS )
297 // Variadic templates, rvalue reference
299 template< class T, class... Args >
300 static postconstructor_invoker<T> deconstruct( Args && ... args )
302 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
304 detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
306 void * pv = pd->address();
308 new( pv ) T( detail::forward<Args>( args )... );
309 pd->set_initialized();
311 boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
312 boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
313 return retval;
316 #else
318 template< class T, class A1 >
319 static postconstructor_invoker<T> deconstruct( A1 const & a1 )
321 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
323 detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
325 void * pv = pd->address();
327 new( pv ) T( a1 );
328 pd->set_initialized();
330 boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
331 boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
332 return retval;
335 template< class T, class A1, class A2 >
336 static postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2 )
338 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
340 detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
342 void * pv = pd->address();
344 new( pv ) T( a1, a2 );
345 pd->set_initialized();
347 boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
348 boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
349 return retval;
352 template< class T, class A1, class A2, class A3 >
353 static postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3 )
355 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
357 detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
359 void * pv = pd->address();
361 new( pv ) T( a1, a2, a3 );
362 pd->set_initialized();
364 boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
365 boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
366 return retval;
369 template< class T, class A1, class A2, class A3, class A4 >
370 static postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4 )
372 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
374 detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
376 void * pv = pd->address();
378 new( pv ) T( a1, a2, a3, a4 );
379 pd->set_initialized();
381 boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
382 boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
383 return retval;
386 template< class T, class A1, class A2, class A3, class A4, class A5 >
387 static postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5 )
389 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
391 detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
393 void * pv = pd->address();
395 new( pv ) T( a1, a2, a3, a4, a5 );
396 pd->set_initialized();
398 boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
399 boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
400 return retval;
403 template< class T, class A1, class A2, class A3, class A4, class A5, class A6 >
404 static postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6 )
406 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
408 detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
410 void * pv = pd->address();
412 new( pv ) T( a1, a2, a3, a4, a5, a6 );
413 pd->set_initialized();
415 boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
416 boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
417 return retval;
420 template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 >
421 static postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7 )
423 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
425 detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
427 void * pv = pd->address();
429 new( pv ) T( a1, a2, a3, a4, a5, a6, a7 );
430 pd->set_initialized();
432 boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
433 boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
434 return retval;
437 template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 >
438 static postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8 )
440 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
442 detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
444 void * pv = pd->address();
446 new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 );
447 pd->set_initialized();
449 boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
450 boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
451 return retval;
454 template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 >
455 static postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8, A9 const & a9 )
457 boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
459 detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
461 void * pv = pd->address();
463 new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 );
464 pd->set_initialized();
466 boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
467 boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
468 return retval;
471 #endif
474 // Zero-argument versions
476 // Used even when variadic templates are available because of the new T() vs new T issue
478 template< class T > postconstructor_invoker<T> deconstruct()
480 return deconstruct_access::deconstruct<T>();
483 #if defined( BOOST_HAS_VARIADIC_TMPL ) && defined( BOOST_HAS_RVALUE_REFS )
485 // Variadic templates, rvalue reference
487 template< class T, class... Args > postconstructor_invoker< T > deconstruct( Args && ... args )
489 return deconstruct_access::deconstruct<T>( detail::forward<Args>( args )... );
492 #else
494 // C++03 version
496 template< class T, class A1 >
497 postconstructor_invoker<T> deconstruct( A1 const & a1 )
499 return deconstruct_access::deconstruct<T>(a1);
502 template< class T, class A1, class A2 >
503 postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2 )
505 return deconstruct_access::deconstruct<T>(a1,a2);
508 template< class T, class A1, class A2, class A3 >
509 postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3 )
511 return deconstruct_access::deconstruct<T>(a1,a2,a3);
514 template< class T, class A1, class A2, class A3, class A4 >
515 postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4 )
517 return deconstruct_access::deconstruct<T>(a1,a2,a3,a4);
520 template< class T, class A1, class A2, class A3, class A4, class A5 >
521 postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5 )
523 return deconstruct_access::deconstruct<T>(a1,a2,a3,a4,a5);
526 template< class T, class A1, class A2, class A3, class A4, class A5, class A6 >
527 postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6 )
529 return deconstruct_access::deconstruct<T>(a1,a2,a3,a4,a5,a6);
532 template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 >
533 postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7 )
535 return deconstruct_access::deconstruct<T>(a1,a2,a3,a4,a5,a6,a7);
538 template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 >
539 postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8 )
541 return deconstruct_access::deconstruct<T>(a1,a2,a3,a4,a5,a6,a7,a8);
544 template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 >
545 postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8, A9 const & a9 )
547 return deconstruct_access::deconstruct<T>(a1,a2,a3,a4,a5,a6,a7,a8,a9);
550 #endif
552 } // namespace signals2
553 } // namespace boost
555 #endif // #ifndef BOOST_SIGNALS2_DECONSTRUCT_HPP