[2.2.1] Apply reviewed header file (Base to Collection)
[platform/framework/native/appfw.git] / inc / unique_ptr.hpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // unique_ptr.hpp header file
3 //
4 // Copyright 2009 Howard Hinnant, Ion Gaztañaga.
5 // Distributed under the Boost Software License, Version 1.0. (See
6 // accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8 // See http://www.boost.org/libs/foreach for documentation
9
10 // This is a C++03 emulation of std::unique_ptr placed in namespace boost.
11 // Reference http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2800.pdf
12 //   for the latest unique_ptr specification, and
13 //   reference http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html
14 //   for any pending issues against this specification.
15
16 #ifndef _BOOST_UNIQUE_PTR_HPP_
17 #define _BOOST_UNIQUE_PTR_HPP_
18
19 //#include <memory>
20 #include <boost/utility/enable_if.hpp>
21 #include <boost/type_traits.hpp>
22 #include <boost/static_assert.hpp>
23 #include <boost/mpl/if.hpp>
24
25 namespace boost
26 {
27
28 namespace detail_unique_ptr
29 {
30
31 typedef char one;
32 struct two {one _[2];};
33
34 // An is_convertible<From, To> that considers From an rvalue (consistent with C++0X).
35 //   This is a simplified version neglecting the types function, array, void and abstract types
36 //   I had to make a special case out of is_convertible<T,T> to make move-only
37 //   types happy.
38
39 namespace is_conv_imp
40 {
41 template <class T> one test1(const T&);
42 template <class T> two test1(...);
43 template <class T> one test2(T);
44 template <class T> two test2(...);
45 template <class T> T source();
46 }
47
48 template <class T1, class T2>
49 struct is_convertible
50 {
51     static const bool value = sizeof(is_conv_imp::test1<T2>(is_conv_imp::source<T1>())) == 1;
52 };
53
54 template <class T>
55 struct is_convertible<T, T>
56 {
57     static const bool value = sizeof(is_conv_imp::test2<T>(is_conv_imp::source<T>())) == 1;
58 };
59
60 template <class T>
61 class rv
62 {
63     T& r_;
64
65 public:
66     explicit rv(T& r) : r_(r) {}
67     T* operator->() {return &r_;}
68     T& operator*() {return r_;}
69 };
70
71 template <class T>
72 struct identity
73 {
74     typedef T type;
75 };
76
77 }  // detail_unique_ptr
78
79 template <class T>
80 inline
81 typename enable_if_c
82 <
83     !detail_unique_ptr::is_convertible<T, detail_unique_ptr::rv<T> >::value,
84     T&
85 >::type
86 move(T& t)
87 {
88     return t;
89 }
90
91 template <class T>
92 inline
93 typename enable_if_c
94 <
95     !detail_unique_ptr::is_convertible<T, detail_unique_ptr::rv<T> >::value,
96     const T&
97 >::type
98 move(const T& t)
99 {
100     return t;
101 }
102
103 template <class T>
104 inline
105 typename enable_if_c
106 <
107     detail_unique_ptr::is_convertible<T, detail_unique_ptr::rv<T> >::value,
108     T
109 >::type
110 move(T& t)
111 {
112     return T(detail_unique_ptr::rv<T>(t));
113 }
114
115 template <class T>
116 inline
117 typename enable_if_c
118 <
119     is_reference<T>::value,
120     T
121 >::type
122 forward(typename detail_unique_ptr::identity<T>::type t)
123 {
124     return t;
125 }
126
127 template <class T>
128 inline
129 typename enable_if_c
130 <
131     !is_reference<T>::value,
132     T
133 >::type
134 forward(typename detail_unique_ptr::identity<T>::type& t)
135 {
136     return boost::move(t);
137 }
138
139 template <class T>
140 inline
141 typename enable_if_c
142 <
143     !is_reference<T>::value,
144     T
145 >::type
146 forward(const typename detail_unique_ptr::identity<T>::type& t)
147 {
148     return boost::move(const_cast<T&>(t));
149 }
150
151 namespace detail_unique_ptr {
152
153 // A move-aware but stripped-down compressed_pair which only optimizes storage for T2
154 template <class T1, class T2, bool = is_empty<T2>::value>
155 class unique_ptr_storage
156 {
157     T1 t1_;
158     T2 t2_;
159
160     typedef typename add_reference<T2>::type T2_reference;
161     typedef typename add_reference<const T2>::type T2_const_reference;
162
163     unique_ptr_storage(const unique_ptr_storage&);
164     unique_ptr_storage& operator=(const unique_ptr_storage&);
165 public:
166     operator rv<unique_ptr_storage>() {return rv<unique_ptr_storage>(*this);}
167
168     unique_ptr_storage() : t1_(), t2_() {}
169
170     explicit unique_ptr_storage(T1 t1)
171         : t1_(boost::move(t1)), t2_() {}
172
173     unique_ptr_storage(T1 t1, T2 t2)
174         : t1_(boost::move(t1)), t2_(boost::forward<T2>(t2)) {}
175
176           T1& first()       {return t1_;}
177     const T1& first() const {return t1_;}
178
179           T2_reference second()       {return t2_;}
180     T2_const_reference second() const {return t2_;}
181 };
182
183 template <class T1, class T2>
184 class unique_ptr_storage<T1, T2, true>
185     : private T2
186 {
187     T1 t1_;
188     typedef T2 t2_;
189
190     unique_ptr_storage(const unique_ptr_storage&);
191     unique_ptr_storage& operator=(const unique_ptr_storage&);
192 public:
193     operator rv<unique_ptr_storage>() {return rv<unique_ptr_storage>(*this);}
194
195     unique_ptr_storage() : t1_() {}
196
197     explicit unique_ptr_storage(T1 t1)
198         : t1_(boost::move(t1)) {}
199
200     unique_ptr_storage(T1 t1, T2 t2)
201         : t2_(boost::move(t2)), t1_(boost::move(t1)) {}
202
203           T1& first()       {return t1_;}
204     const T1& first() const {return t1_;}
205
206           T2& second()       {return *this;}
207     const T2& second() const {return *this;}
208 };
209
210 template <class T1, class T2, bool b>
211 inline
212 void
213 swap(unique_ptr_storage<T1, T2, b>& x, unique_ptr_storage<T1, T2, b>& y)
214 {
215     using std::swap;
216     swap(x.first(), y.first());
217     swap(x.second(), y.second());
218 }
219
220 }  // detail_unique_ptr
221
222 template <class T>
223 struct default_delete
224 {
225     default_delete() {}
226     template <class U>
227         default_delete(const default_delete<U>&,
228             typename enable_if_c<detail_unique_ptr::is_convertible<U*, T*>::value>::type* = 0)
229         {}
230
231     void operator()(T* ptr) const
232     {
233         BOOST_STATIC_ASSERT(sizeof(T) > 0);
234         delete ptr;
235     }
236 };
237
238 template <class T>
239 struct default_delete<T[]>
240 {
241     void operator()(T* ptr) const
242     {
243         BOOST_STATIC_ASSERT(sizeof(T) > 0);
244         delete [] ptr;
245     }
246
247 private:
248
249     template <class U> void operator()(U*) const;
250 };
251
252 namespace detail_unique_ptr
253 {
254
255 namespace pointer_type_imp
256 {
257
258 template <class U> static two test(...);
259 template <class U> static one test(typename U::pointer* = 0);
260
261 }  // pointer_type_imp
262
263 template <class T>
264 struct has_pointer_type
265 {
266     static const bool value = sizeof(pointer_type_imp::test<T>(0)) == 1;
267 };
268
269 namespace pointer_type_imp
270 {
271
272 template <class T, class D, bool = has_pointer_type<D>::value>
273 struct pointer_type
274 {
275     typedef typename D::pointer type;
276 };
277
278 template <class T, class D>
279 struct pointer_type<T, D, false>
280 {
281     typedef T* type;
282 };
283
284 }  // pointer_type_imp
285
286 template <class T, class D>
287 struct pointer_type
288 {
289     typedef typename pointer_type_imp::pointer_type<T,
290         typename boost::remove_reference<D>::type>::type type;
291 };
292
293 }  // detail_unique_ptr
294
295 template <class T, class D = default_delete<T> >
296 class unique_ptr
297 {
298 public:
299     typedef T element_type;
300     typedef D deleter_type;
301     typedef typename detail_unique_ptr::pointer_type<element_type, deleter_type>::type pointer;
302
303 private:
304     detail_unique_ptr::unique_ptr_storage<pointer, deleter_type> ptr_;
305
306     typedef typename add_reference<deleter_type>::type deleter_reference;
307     typedef typename add_reference<const deleter_type>::type deleter_const_reference;
308
309     struct nat {int for_bool_;};
310
311     unique_ptr(unique_ptr&);
312     unique_ptr& operator=(unique_ptr&);
313
314 public:
315     operator detail_unique_ptr::rv<unique_ptr>() {return detail_unique_ptr::rv<unique_ptr>(*this);}
316     unique_ptr(detail_unique_ptr::rv<unique_ptr> r) : ptr_(r->release(), boost::forward<deleter_type>(r->get_deleter())) {}
317     unique_ptr& operator=(detail_unique_ptr::rv<unique_ptr> r)
318     {
319         reset(r->release());
320         ptr_.second() = boost::move(r->get_deleter());
321         return *this;
322     }
323
324     unique_ptr()
325         {
326             BOOST_STATIC_ASSERT(!is_reference<deleter_type>::value);
327             BOOST_STATIC_ASSERT(!is_pointer<deleter_type>::value);
328         }
329
330     explicit unique_ptr(pointer p)
331         : ptr_(p)
332         {
333             BOOST_STATIC_ASSERT(!is_reference<deleter_type>::value);
334             BOOST_STATIC_ASSERT(!is_pointer<deleter_type>::value);
335         }
336
337     unique_ptr(pointer p, typename mpl::if_<is_reference<D>,
338                           volatile typename remove_reference<D>::type&, D>::type d)
339         : ptr_(boost::move(p), boost::forward<D>(const_cast<typename add_reference<D>::type>(d))) {}
340
341     template <class U, class E>
342         unique_ptr(unique_ptr<U, E> u,
343             typename enable_if_c
344                 <
345                 !boost::is_array<U>::value &&
346                 detail_unique_ptr::is_convertible<typename unique_ptr<U>::pointer, pointer>::value &&
347                 detail_unique_ptr::is_convertible<E, deleter_type>::value &&
348                 (
349                     !is_reference<deleter_type>::value ||
350                      is_same<deleter_type, E>::value
351                 )
352                 >::type* = 0)
353             : ptr_(u.release(), boost::forward<D>(boost::forward<E>(u.get_deleter()))) {}
354
355     ~unique_ptr() {reset();}
356
357     unique_ptr& operator=(int nat::*)
358     {
359         reset();
360         return *this;
361     }
362
363     template <class U, class E>
364         unique_ptr&
365         operator=(unique_ptr<U, E> u)
366         {
367             reset(u.release());
368             ptr_.second() = boost::move(u.get_deleter());
369             return *this;
370         }
371
372     typename add_reference<T>::type operator*() const {return *get();}
373     pointer operator->() const {return get();}
374     pointer get() const {return ptr_.first();}
375     deleter_reference       get_deleter()       {return ptr_.second();}
376     deleter_const_reference get_deleter() const {return ptr_.second();}
377     operator int nat::*() const {return get() ? &nat::for_bool_ : 0;}
378
379     void reset(pointer p = pointer())
380     {
381         pointer t = get();
382         if (t != pointer())
383             get_deleter()(t);
384         ptr_.first() = p;
385     }
386
387     pointer release()
388     {
389         pointer tmp = get();
390         ptr_.first() = pointer();
391         return tmp;
392     }
393
394     void swap(unique_ptr& u) {detail_unique_ptr::swap(ptr_, u.ptr_);}
395 };
396
397 template <class T, class D>
398 class unique_ptr<T[], D>
399 {
400 public:
401     typedef T element_type;
402     typedef D deleter_type;
403     typedef typename detail_unique_ptr::pointer_type<element_type, deleter_type>::type pointer;
404
405 private:
406     detail_unique_ptr::unique_ptr_storage<pointer, deleter_type> ptr_;
407
408     typedef typename add_reference<deleter_type>::type deleter_reference;
409     typedef typename add_reference<const deleter_type>::type deleter_const_reference;
410
411     struct nat {int for_bool_;};
412
413     unique_ptr(unique_ptr&);
414     unique_ptr& operator=(unique_ptr&);
415
416 public:
417     operator detail_unique_ptr::rv<unique_ptr>() {return detail_unique_ptr::rv<unique_ptr>(*this);}
418     unique_ptr(detail_unique_ptr::rv<unique_ptr> r) : ptr_(r->release(), boost::forward<deleter_type>(r->get_deleter())) {}
419     unique_ptr& operator=(detail_unique_ptr::rv<unique_ptr> r)
420     {
421         reset(r->release());
422         ptr_.second() = boost::move(r->get_deleter());
423         return *this;
424     }
425
426     unique_ptr()
427         {
428             BOOST_STATIC_ASSERT(!is_reference<deleter_type>::value);
429             BOOST_STATIC_ASSERT(!is_pointer<deleter_type>::value);
430         }
431
432     explicit unique_ptr(pointer p)
433         : ptr_(p)
434         {
435             BOOST_STATIC_ASSERT(!is_reference<deleter_type>::value);
436             BOOST_STATIC_ASSERT(!is_pointer<deleter_type>::value);
437         }
438
439     unique_ptr(pointer p, typename mpl::if_<is_reference<D>,
440                           volatile typename remove_reference<D>::type&, D>::type d)
441         : ptr_(boost::move(p), boost::forward<D>(const_cast<typename add_reference<D>::type>(d))) {}
442
443     ~unique_ptr() {reset();}
444
445     T& operator[](size_t i) const {return get()[i];}
446     pointer get() const {return ptr_.first();}
447     deleter_reference       get_deleter()       {return ptr_.second();}
448     deleter_const_reference get_deleter() const {return ptr_.second();}
449     operator int nat::*() const {return get() ? &nat::for_bool_ : 0;}
450
451     void reset(pointer p = pointer())
452     {
453         pointer t = get();
454         if (t != pointer())
455             get_deleter()(t);
456         ptr_.first() = p;
457     }
458
459     pointer release()
460     {
461         pointer tmp = get();
462         ptr_.first() = pointer();
463         return tmp;
464     }
465
466     void swap(unique_ptr& u) {detail_unique_ptr::swap(ptr_, u.ptr_);}
467 private:
468     template <class U>
469         explicit unique_ptr(U,
470             typename enable_if_c<detail_unique_ptr::is_convertible<U, pointer>::value>::type* = 0);
471
472     template <class U>
473         unique_ptr(U, typename mpl::if_<is_reference<D>,
474                           volatile typename remove_reference<D>::type&, D>::type,
475                           typename enable_if_c<detail_unique_ptr::is_convertible<U, pointer>::value>::type* = 0);
476 };
477
478 template<class T, class D>
479 inline
480 void
481 swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y)
482 {
483     x.swap(y);
484 }
485
486 template<class T1, class D1, class T2, class D2>
487 inline
488 bool
489 operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
490 {
491     return x.get() == y.get();
492 }
493
494 template<class T1, class D1, class T2, class D2>
495 inline
496 bool
497 operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
498 {
499     return !(x == y);
500 }
501
502 template<class T1, class D1, class T2, class D2> 
503 inline
504 bool
505 operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
506 {
507     return x.get() < y.get();
508 }
509
510 template<class T1, class D1, class T2, class D2> 
511 inline
512 bool
513 operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
514 {
515     return !(y < x);
516 }
517
518 template<class T1, class D1, class T2, class D2> 
519 inline
520 bool
521 operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
522 {
523     return y < x;
524 }
525
526 template<class T1, class D1, class T2, class D2> 
527 inline
528 bool
529 operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
530 {
531     return !(x < y);
532 }
533
534 }  // boost
535
536 #endif  // _BOOST_UNIQUE_PTR_HPP_