Imported Upstream version 1.57.0
[platform/upstream/boost.git] / boost / signals2 / deconstruct.hpp
1 #ifndef BOOST_SIGNALS2_DECONSTRUCT_HPP
2 #define BOOST_SIGNALS2_DECONSTRUCT_HPP
3
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.
13 //
14 //  based on make_shared.hpp and make_shared_access patch from Michael Marcin
15 //
16 //  Copyright (c) 2007, 2008 Peter Dimov
17 //  Copyright (c) 2008 Michael Marcin
18 //  Copyright (c) 2009 Frank Mori Hess
19 //
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
23 //
24 //  See http://www.boost.org
25 //  for more information
26
27 #include <boost/config.hpp>
28 #include <boost/shared_ptr.hpp>
29 #include <boost/type_traits/alignment_of.hpp>
30 #include <boost/type_traits/remove_const.hpp>
31 #include <boost/type_traits/type_with_alignment.hpp>
32 #include <cstddef>
33 #include <new>
34
35 namespace boost
36 {
37   template<typename T> class enable_shared_from_this;
38
39 namespace signals2
40 {
41   class deconstruct_access;
42
43 namespace detail
44 {
45   inline void adl_predestruct(...) {}
46 } // namespace detail
47
48 template<typename T>
49     class postconstructor_invoker
50 {
51 public:
52     operator const shared_ptr<T> & () const
53     {
54         return postconstruct();
55     }
56     const shared_ptr<T>& postconstruct() const
57     {
58         if(!_postconstructed)
59         {
60             adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()));
61             _postconstructed = true;
62         }
63         return _sp;
64     }
65 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
66     template<class... Args>
67       const shared_ptr<T>& postconstruct(Args && ... args)
68     {
69         if(!_postconstructed)
70         {
71             adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()),
72                 std::forward<Args>(args)...);
73             _postconstructed = true;
74         }
75         return _sp;
76     }
77 #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
78     template<typename A1>
79       const shared_ptr<T>& postconstruct(const A1 &a1) const
80     {
81         if(!_postconstructed)
82         {
83             adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()),
84                 a1);
85             _postconstructed = true;
86         }
87         return _sp;
88     }
89     template<typename A1, typename A2>
90       const shared_ptr<T>& postconstruct(const A1 &a1, const A2 &a2) const
91     {
92         if(!_postconstructed)
93         {
94             adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()),
95                 a1, a2);
96             _postconstructed = true;
97         }
98         return _sp;
99     }
100     template<typename A1, typename A2, typename A3>
101       const shared_ptr<T>& postconstruct(const A1 &a1, const A2 &a2, const A3 &a3) const
102     {
103         if(!_postconstructed)
104         {
105             adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()),
106                 a1, a2, a3);
107             _postconstructed = true;
108         }
109         return _sp;
110     }
111     template<typename A1, typename A2, typename A3, typename A4>
112       const shared_ptr<T>& postconstruct(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4) const
113     {
114         if(!_postconstructed)
115         {
116             adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()),
117                 a1, a2, a3, a4);
118             _postconstructed = true;
119         }
120         return _sp;
121     }
122     template<typename A1, typename A2, typename A3, typename A4, typename A5>
123       const shared_ptr<T>& postconstruct(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5) const
124     {
125         if(!_postconstructed)
126         {
127             adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()),
128                 a1, a2, a3, a4, a5);
129             _postconstructed = true;
130         }
131         return _sp;
132     }
133     template<typename A1, typename A2, typename A3, typename A4, typename A5,
134       typename A6>
135       const shared_ptr<T>& postconstruct(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5,
136       const A6 &a6) const
137     {
138         if(!_postconstructed)
139         {
140             adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()),
141                 a1, a2, a3, a4, a5, a6);
142             _postconstructed = true;
143         }
144         return _sp;
145     }
146     template<typename A1, typename A2, typename A3, typename A4, typename A5,
147       typename A6, typename A7>
148       const shared_ptr<T>& postconstruct(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5,
149       const A6 &a6, const A7 &a7) const
150     {
151         if(!_postconstructed)
152         {
153             adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()),
154                 a1, a2, a3, a4, a5, a6, a7);
155             _postconstructed = true;
156         }
157         return _sp;
158     }
159     template<typename A1, typename A2, typename A3, typename A4, typename A5,
160       typename A6, typename A7, typename A8>
161       const shared_ptr<T>& postconstruct(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5,
162       const A6 &a6, const A7 &a7, const A8 &a8) const
163     {
164         if(!_postconstructed)
165         {
166             adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()),
167                 a1, a2, a3, a4, a5, a6, a7, a8);
168             _postconstructed = true;
169         }
170         return _sp;
171     }
172     template<typename A1, typename A2, typename A3, typename A4, typename A5,
173       typename A6, typename A7, typename A8, typename A9>
174       const shared_ptr<T>& postconstruct(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4, const A5 &a5,
175       const A6 &a6, const A7 &a7, const A8 &a8, const A9 &a9) const
176     {
177         if(!_postconstructed)
178         {
179             adl_postconstruct(_sp, const_cast<typename boost::remove_const<T>::type *>(_sp.get()),
180                 a1, a2, a3, a4, a5, a6, a7, a8, a9);
181             _postconstructed = true;
182         }
183         return _sp;
184     }
185 #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
186 private:
187     friend class boost::signals2::deconstruct_access;
188     postconstructor_invoker(const shared_ptr<T> & sp):
189         _sp(sp), _postconstructed(false)
190     {}
191     shared_ptr<T> _sp;
192     mutable bool _postconstructed;
193 };
194
195 namespace detail
196 {
197
198 template< std::size_t N, std::size_t A > struct sp_aligned_storage
199 {
200     union type
201     {
202         char data_[ N ];
203         typename boost::type_with_alignment< A >::type align_;
204     };
205 };
206
207 template< class T > class deconstruct_deleter
208 {
209 private:
210
211     typedef typename sp_aligned_storage< sizeof( T ), ::boost::alignment_of< T >::value >::type storage_type;
212
213     bool initialized_;
214     storage_type storage_;
215
216 private:
217
218     void destroy()
219     {
220         if( initialized_ )
221         {
222             T* p = reinterpret_cast< T* >( storage_.data_ );
223             using boost::signals2::detail::adl_predestruct;
224             adl_predestruct(const_cast<typename boost::remove_const<T>::type *>(p));
225             p->~T();
226             initialized_ = false;
227         }
228     }
229
230 public:
231
232     deconstruct_deleter(): initialized_( false )
233     {
234     }
235
236     // this copy constructor is an optimization: we don't need to copy the storage_ member,
237     // and shouldn't be copying anyways after initialized_ becomes true
238     deconstruct_deleter(const deconstruct_deleter &): initialized_( false )
239     {
240     }
241
242     ~deconstruct_deleter()
243     {
244         destroy();
245     }
246
247     void operator()( T * )
248     {
249         destroy();
250     }
251
252     void * address()
253     {
254         return storage_.data_;
255     }
256
257     void set_initialized()
258     {
259         initialized_ = true;
260     }
261 };
262 }  // namespace detail
263
264 class deconstruct_access
265 {
266 public:
267
268     template< class T >
269     static postconstructor_invoker<T> deconstruct()
270     {
271         boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
272
273         detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
274
275         void * pv = pd->address();
276
277         new( pv ) T();
278         pd->set_initialized();
279
280         boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
281         boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
282         return retval;
283
284     }
285
286 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
287
288     // Variadic templates, rvalue reference
289
290     template< class T, class... Args >
291     static postconstructor_invoker<T> deconstruct( Args && ... args )
292     {
293         boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
294
295         detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
296
297         void * pv = pd->address();
298
299         new( pv ) T( std::forward<Args>( args )... );
300         pd->set_initialized();
301
302         boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
303         boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
304         return retval;
305     }
306
307 #else
308
309     template< class T, class A1 >
310     static postconstructor_invoker<T> deconstruct( A1 const & a1 )
311     {
312         boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
313
314         detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
315
316         void * pv = pd->address();
317
318         new( pv ) T( a1 );
319         pd->set_initialized();
320
321         boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
322         boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
323         return retval;
324     }
325
326     template< class T, class A1, class A2 >
327     static postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2 )
328     {
329         boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
330
331         detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
332
333         void * pv = pd->address();
334
335         new( pv ) T( a1, a2 );
336         pd->set_initialized();
337
338         boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
339         boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
340         return retval;
341     }
342
343     template< class T, class A1, class A2, class A3 >
344     static postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3 )
345     {
346         boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
347
348         detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
349
350         void * pv = pd->address();
351
352         new( pv ) T( a1, a2, a3 );
353         pd->set_initialized();
354
355         boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
356         boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
357         return retval;
358     }
359
360     template< class T, class A1, class A2, class A3, class A4 >
361     static postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4 )
362     {
363         boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
364
365         detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
366
367         void * pv = pd->address();
368
369         new( pv ) T( a1, a2, a3, a4 );
370         pd->set_initialized();
371
372         boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
373         boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
374         return retval;
375     }
376
377     template< class T, class A1, class A2, class A3, class A4, class A5 >
378     static postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5 )
379     {
380         boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
381
382         detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
383
384         void * pv = pd->address();
385
386         new( pv ) T( a1, a2, a3, a4, a5 );
387         pd->set_initialized();
388
389         boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
390         boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
391         return retval;
392     }
393
394     template< class T, class A1, class A2, class A3, class A4, class A5, class A6 >
395     static postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6 )
396     {
397         boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
398
399         detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
400
401         void * pv = pd->address();
402
403         new( pv ) T( a1, a2, a3, a4, a5, a6 );
404         pd->set_initialized();
405
406         boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
407         boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
408         return retval;
409     }
410
411     template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 >
412     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 )
413     {
414         boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
415
416         detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
417
418         void * pv = pd->address();
419
420         new( pv ) T( a1, a2, a3, a4, a5, a6, a7 );
421         pd->set_initialized();
422
423         boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
424         boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
425         return retval;
426     }
427
428     template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 >
429     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 )
430     {
431         boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
432
433         detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
434
435         void * pv = pd->address();
436
437         new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 );
438         pd->set_initialized();
439
440         boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
441         boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
442         return retval;
443     }
444
445     template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 >
446     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 )
447     {
448         boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::deconstruct_deleter< T >() );
449
450         detail::deconstruct_deleter< T > * pd = boost::get_deleter< detail::deconstruct_deleter< T > >( pt );
451
452         void * pv = pd->address();
453
454         new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 );
455         pd->set_initialized();
456
457         boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
458         boost::detail::sp_enable_shared_from_this(&retval, retval.get(), retval.get());
459         return retval;
460     }
461
462 #endif
463 };
464
465 // Zero-argument versions
466 //
467 // Used even when variadic templates are available because of the new T() vs new T issue
468
469 template< class T > postconstructor_invoker<T> deconstruct()
470 {
471     return deconstruct_access::deconstruct<T>();
472 }
473
474 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
475
476 // Variadic templates, rvalue reference
477
478 template< class T, class... Args > postconstructor_invoker< T > deconstruct( Args && ... args )
479 {
480     return deconstruct_access::deconstruct<T>( std::forward<Args>( args )... );
481 }
482
483 #else
484
485 // C++03 version
486
487 template< class T, class A1 >
488 postconstructor_invoker<T> deconstruct( A1 const & a1 )
489 {
490     return deconstruct_access::deconstruct<T>(a1);
491 }
492
493 template< class T, class A1, class A2 >
494 postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2 )
495 {
496     return deconstruct_access::deconstruct<T>(a1,a2);
497 }
498
499 template< class T, class A1, class A2, class A3 >
500 postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3 )
501 {
502     return deconstruct_access::deconstruct<T>(a1,a2,a3);
503 }
504
505 template< class T, class A1, class A2, class A3, class A4 >
506 postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4 )
507 {
508     return deconstruct_access::deconstruct<T>(a1,a2,a3,a4);
509 }
510
511 template< class T, class A1, class A2, class A3, class A4, class A5 >
512 postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5 )
513 {
514     return deconstruct_access::deconstruct<T>(a1,a2,a3,a4,a5);
515 }
516
517 template< class T, class A1, class A2, class A3, class A4, class A5, class A6 >
518 postconstructor_invoker<T> deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6 )
519 {
520     return deconstruct_access::deconstruct<T>(a1,a2,a3,a4,a5,a6);
521 }
522
523 template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 >
524 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 )
525 {
526     return deconstruct_access::deconstruct<T>(a1,a2,a3,a4,a5,a6,a7);
527 }
528
529 template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 >
530 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 )
531 {
532     return deconstruct_access::deconstruct<T>(a1,a2,a3,a4,a5,a6,a7,a8);
533 }
534
535 template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 >
536 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 )
537 {
538     return deconstruct_access::deconstruct<T>(a1,a2,a3,a4,a5,a6,a7,a8,a9);
539 }
540
541 #endif
542
543 } // namespace signals2
544 } // namespace boost
545
546 #endif // #ifndef BOOST_SIGNALS2_DECONSTRUCT_HPP