1 #ifndef BOOST_SIGNALS2_DECONSTRUCT_HPP
2 #define BOOST_SIGNALS2_DECONSTRUCT_HPP
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>
38 template<typename T
> class enable_shared_from_this
;
42 class deconstruct_access
;
47 #if defined( BOOST_HAS_RVALUE_REFS )
48 template< class T
> T
&& forward( T
&&t
)
54 inline void adl_predestruct(...) {}
58 class postconstructor_invoker
61 operator const shared_ptr
<T
> & () const
63 return postconstruct();
65 const shared_ptr
<T
>& postconstruct() const
69 adl_postconstruct(_sp
, const_cast<typename
boost::remove_const
<T
>::type
*>(_sp
.get()));
70 _postconstructed
= true;
74 #if defined( BOOST_HAS_VARIADIC_TMPL ) && defined( BOOST_HAS_RVALUE_REFS )
75 template<class... Args
>
76 const shared_ptr
<T
>& postconstruct(Args
&& ... args
)
80 adl_postconstruct(_sp
, const_cast<typename
boost::remove_const
<T
>::type
*>(_sp
.get()),
81 detail::forward
<Args
>(args
)...);
82 _postconstructed
= true;
88 const shared_ptr
<T
>& postconstruct(const A1
&a1
) const
92 adl_postconstruct(_sp
, const_cast<typename
boost::remove_const
<T
>::type
*>(_sp
.get()),
94 _postconstructed
= true;
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()),
105 _postconstructed
= true;
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()),
116 _postconstructed
= true;
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()),
127 _postconstructed
= true;
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()),
138 _postconstructed
= true;
142 template<typename A1
, typename A2
, typename A3
, typename A4
, typename A5
,
144 const shared_ptr
<T
>& postconstruct(const A1
&a1
, const A2
&a2
, const A3
&a3
, const A4
&a4
, const A5
&a5
,
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;
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;
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;
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;
194 #endif // else defined( BOOST_HAS_VARIADIC_TMPL ) && defined( BOOST_HAS_RVALUE_REFS )
196 friend class boost::signals2::deconstruct_access
;
197 postconstructor_invoker(const shared_ptr
<T
> & sp
):
198 _sp(sp
), _postconstructed(false)
201 mutable bool _postconstructed
;
207 template< std::size_t N
, std::size_t A
> struct sp_aligned_storage
212 typename
boost::type_with_alignment
< A
>::type align_
;
216 template< class T
> class deconstruct_deleter
220 typedef typename sp_aligned_storage
< sizeof( T
), ::boost::alignment_of
< T
>::value
>::type storage_type
;
223 storage_type storage_
;
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
));
235 initialized_
= false;
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()
256 void operator()( T
* )
263 return storage_
.data_
;
266 void set_initialized()
271 } // namespace detail
273 class deconstruct_access
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();
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());
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());
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();
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());
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());
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());
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());
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());
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());
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());
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());
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());
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
)... );
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
);
552 } // namespace signals2
555 #endif // #ifndef BOOST_SIGNALS2_DECONSTRUCT_HPP