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