fix doc example typo
[boost.git] / boost / interprocess / smart_ptr / unique_ptr.hpp
blob36a75073996dd294488389f7d65d70f69f9b5266
1 //////////////////////////////////////////////////////////////////////////////
2 // I, Howard Hinnant, hereby place this code in the public domain.
3 //////////////////////////////////////////////////////////////////////////////
4 //
5 // This file is the adaptation for Interprocess of
6 // Howard Hinnant's unique_ptr emulation code.
7 //
8 // (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost
9 // Software License, Version 1.0. (See accompanying file
10 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
12 // See http://www.boost.org/libs/interprocess for documentation.
14 //////////////////////////////////////////////////////////////////////////////
16 #ifndef BOOST_INTERPROCESS_UNIQUE_PTR_HPP_INCLUDED
17 #define BOOST_INTERPROCESS_UNIQUE_PTR_HPP_INCLUDED
19 #include <boost/interprocess/detail/config_begin.hpp>
20 #include <boost/interprocess/detail/workaround.hpp>
21 #include <boost/assert.hpp>
22 #include <boost/interprocess/detail/utilities.hpp>
23 #include <boost/interprocess/detail/pointer_type.hpp>
24 #include <boost/interprocess/detail/move.hpp>
25 #include <boost/compressed_pair.hpp>
26 #include <boost/static_assert.hpp>
27 #include <boost/interprocess/detail/mpl.hpp>
28 #include <boost/interprocess/detail/type_traits.hpp>
29 #include <boost/interprocess/smart_ptr/deleter.hpp>
30 #include <cstddef>
32 //!\file
33 //!Describes the smart pointer unique_ptr
35 namespace boost{
36 namespace interprocess{
38 /// @cond
39 template <class T, class D> class unique_ptr;
41 namespace detail {
43 template <class T> struct unique_ptr_error;
45 template <class T, class D>
46 struct unique_ptr_error<const unique_ptr<T, D> >
48 typedef unique_ptr<T, D> type;
51 } //namespace detail {
52 /// @endcond
54 //!Template unique_ptr stores a pointer to an object and deletes that object
55 //!using the associated deleter when it is itself destroyed (such as when
56 //!leaving block scope.
57 //!
58 //!The unique_ptr provides a semantics of strict ownership. A unique_ptr owns the
59 //!object it holds a pointer to.
60 //!
61 //!A unique_ptr is not CopyConstructible, nor CopyAssignable, however it is
62 //!MoveConstructible and Move-Assignable.
63 //!
64 //!The uses of unique_ptr include providing exception safety for dynamically
65 //!allocated memory, passing ownership of dynamically allocated memory to a
66 //!function, and returning dynamically allocated memory from a function
67 //!
68 //!A client-supplied template argument D must be a
69 //!function pointer or functor for which, given a value d of type D and a pointer
70 //!ptr to a type T*, the expression d(ptr) is
71 //!valid and has the effect of deallocating the pointer as appropriate for that
72 //!deleter. D may also be an lvalue-reference to a deleter.
73 //!
74 //!If the deleter D maintains state, it is intended that this state stay with
75 //!the associated pointer as ownership is transferred
76 //!from unique_ptr to unique_ptr. The deleter state need never be copied,
77 //!only moved or swapped as pointer ownership
78 //!is moved around. That is, the deleter need only be MoveConstructible,
79 //!MoveAssignable, and Swappable, and need not be CopyConstructible
80 //!(unless copied into the unique_ptr) nor CopyAssignable.
81 template <class T, class D>
82 class unique_ptr
84 /// @cond
85 struct nat {int for_bool_;};
86 typedef typename detail::add_reference<D>::type deleter_reference;
87 typedef typename detail::add_reference<const D>::type deleter_const_reference;
88 /// @endcond
90 public:
91 BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(unique_ptr)
93 typedef T element_type;
94 typedef D deleter_type;
95 typedef typename detail::pointer_type<T, D>::type pointer;
97 //!Requires: D must be default constructible, and that construction must not
98 //!throw an exception. D must not be a reference type.
99 //!
100 //!Effects: Constructs a unique_ptr which owns nothing.
102 //!Postconditions: get() == 0. get_deleter() returns a reference to a
103 //!default constructed deleter D.
105 //!Throws: nothing.
106 unique_ptr()
107 : ptr_(pointer(0))
110 //!Requires: The expression D()(p) must be well formed. The default constructor
111 //!of D must not throw an exception.
113 //!D must not be a reference type.
115 //!Effects: Constructs a unique_ptr which owns p.
117 //!Postconditions: get() == p. get_deleter() returns a reference to a default constructed deleter D.
119 //!Throws: nothing.
120 explicit unique_ptr(pointer p)
121 : ptr_(p)
124 //!Requires: The expression d(p) must be well formed.
126 //!Postconditions: get() == p. get_deleter() returns a reference to the
127 //!internally stored deleter. If D is a
128 //!reference type then get_deleter() returns a reference to the lvalue d.
130 //!Throws: nothing.
131 unique_ptr(pointer p
132 ,typename detail::if_<detail::is_reference<D>
134 ,typename detail::add_reference<const D>::type>::type d)
135 : ptr_(p, d)
138 //!Requires: If the deleter is not a reference type, construction of the
139 //!deleter D from an lvalue D must not throw an exception.
141 //!Effects: Constructs a unique_ptr which owns the pointer which u owns
142 //!(if any). If the deleter is not a reference type, it is move constructed
143 //!from u's deleter, otherwise the reference is copy constructed from u's deleter.
145 //!After the construction, u no longer owns a pointer.
146 //![ Note: The deleter constructor can be implemented with
147 //! boost::interprocess::forward<D>. -end note ]
149 //!Postconditions: get() == value u.get() had before the construction.
150 //!get_deleter() returns a reference to the internally stored deleter which
151 //!was constructed from u.get_deleter(). If D is a reference type then get_-
152 //!deleter() and u.get_deleter() both reference the same lvalue deleter.
154 //!Throws: nothing.
155 unique_ptr(BOOST_INTERPROCESS_RV_REF(unique_ptr) u)
156 : ptr_(u.release(), boost::interprocess::forward<D>(u.get_deleter()))
159 //!Requires: If D is not a reference type, construction of the deleter
160 //!D from an rvalue of type E must be well formed
161 //!and not throw an exception. If D is a reference type, then E must be
162 //!the same type as D (diagnostic required). unique_ptr<U, E>::pointer
163 //!must be implicitly convertible to pointer.
165 //!Effects: Constructs a unique_ptr which owns the pointer which u owns
166 //!(if any). If the deleter is not a reference
167 //!type, it is move constructed from u's deleter, otherwise the reference
168 //!is copy constructed from u's deleter.
170 //!After the construction, u no longer owns a pointer.
172 //!postconditions get() == value u.get() had before the construction,
173 //!modulo any required offset adjustments
174 //!resulting from the cast from U* to T*. get_deleter() returns a reference to the internally stored deleter which
175 //!was constructed from u.get_deleter().
177 //!Throws: nothing.
178 template <class U, class E>
179 unique_ptr(BOOST_INTERPROCESS_RV_REF_2_TEMPL_ARGS(unique_ptr, U, E) u,
180 typename detail::enable_if_c<
181 detail::is_convertible<typename unique_ptr<U, E>::pointer, pointer>::value &&
182 detail::is_convertible<E, D>::value &&
184 !detail::is_reference<D>::value ||
185 detail::is_same<D, E>::value
189 >::type = nat())
190 : ptr_(const_cast<unique_ptr<U,E>&>(u).release(), boost::interprocess::move<D>(u.get_deleter()))
193 //!Effects: If get() == 0 there are no effects. Otherwise get_deleter()(get()).
195 //!Throws: nothing.
196 ~unique_ptr()
197 { reset(); }
199 // assignment
201 //!Requires: Assignment of the deleter D from an rvalue D must not throw an exception.
203 //!Effects: reset(u.release()) followed by a move assignment from u's deleter to
204 //!this deleter.
206 //!Postconditions: This unique_ptr now owns the pointer which u owned, and u no
207 //!longer owns it.
209 //!Returns: *this.
211 //!Throws: nothing.
212 unique_ptr& operator=(BOOST_INTERPROCESS_RV_REF(unique_ptr) u)
214 reset(u.release());
215 ptr_.second() = boost::interprocess::move(u.get_deleter());
216 return *this;
219 //!Requires: Assignment of the deleter D from an rvalue D must not
220 //!throw an exception. U* must be implicitly convertible to T*.
222 //!Effects: reset(u.release()) followed by a move assignment from
223 //!u's deleter to this deleter. If either D or E is
224 //!a reference type, then the referenced lvalue deleter participates
225 //!in the move assignment.
227 //!Postconditions: This unique_ptr now owns the pointer which u owned,
228 //!and u no longer owns it.
230 //!Returns: *this.
232 //!Throws: nothing.
233 template <class U, class E>
234 unique_ptr& operator=(BOOST_INTERPROCESS_RV_REF_2_TEMPL_ARGS(unique_ptr, U, E) u)
236 reset(u.release());
237 ptr_.second() = boost::interprocess::move(u.get_deleter());
238 return *this;
241 //!Assigns from the literal 0 or NULL.
243 //!Effects: reset().
245 //!Postcondition: get() == 0
247 //!Returns: *this.
249 //!Throws: nothing.
250 unique_ptr& operator=(int nat::*)
252 reset();
253 return *this;
256 //!Requires: get() != 0.
257 //!Returns: *get().
258 //!Throws: nothing.
259 typename detail::add_reference<T>::type operator*() const
260 { return *ptr_.first(); }
262 //!Requires: get() != 0.
263 //!Returns: get().
264 //!Throws: nothing.
265 pointer operator->() const
266 { return ptr_.first(); }
268 //!Returns: The stored pointer.
269 //!Throws: nothing.
270 pointer get() const
271 { return ptr_.first(); }
273 //!Returns: A reference to the stored deleter.
275 //!Throws: nothing.
276 deleter_reference get_deleter()
277 { return ptr_.second(); }
279 //!Returns: A const reference to the stored deleter.
281 //!Throws: nothing.
282 deleter_const_reference get_deleter() const
283 { return ptr_.second(); }
285 //!Returns: An unspecified value that, when used in boolean
286 //!contexts, is equivalent to get() != 0.
288 //!Throws: nothing.
289 operator int nat::*() const
290 { return ptr_.first() ? &nat::for_bool_ : 0; }
292 //!Postcondition: get() == 0.
294 //!Returns: The value get() had at the start of the call to release.
296 //!Throws: nothing.
297 pointer release()
299 pointer tmp = ptr_.first();
300 ptr_.first() = 0;
301 return tmp;
304 //!Effects: If p == get() there are no effects. Otherwise get_deleter()(get()).
306 //!Postconditions: get() == p.
308 //!Throws: nothing.
309 void reset(pointer p = 0)
311 if (ptr_.first() != p){
312 if (ptr_.first())
313 ptr_.second()(ptr_.first());
314 ptr_.first() = p;
318 //!Requires: The deleter D is Swappable and will not throw an exception under swap.
320 //!Effects: The stored pointers of this and u are exchanged.
321 //! The stored deleters are swapped (unqualified).
322 //!Throws: nothing.
323 void swap(unique_ptr& u)
324 { ptr_.swap(u.ptr_); }
326 /// @cond
327 private:
328 boost::compressed_pair<pointer, D> ptr_;
330 unique_ptr(unique_ptr&);
331 template <class U, class E> unique_ptr(unique_ptr<U, E>&);
332 template <class U> unique_ptr(U&, typename detail::unique_ptr_error<U>::type = 0);
334 unique_ptr& operator=(unique_ptr&);
335 template <class U, class E> unique_ptr& operator=(unique_ptr<U, E>&);
336 template <class U> typename detail::unique_ptr_error<U>::type operator=(U&);
337 /// @endcond
340 template <class T, class D>
341 class unique_ptr<T[], D>
343 struct nat {int for_bool_;};
344 typedef typename detail::add_reference<D>::type deleter_reference;
345 typedef typename detail::add_reference<const D>::type deleter_const_reference;
346 public:
347 typedef T element_type;
348 typedef D deleter_type;
349 typedef typename detail::pointer_type<T, D>::type pointer;
351 // constructors
352 unique_ptr() : ptr_(pointer()) {}
353 explicit unique_ptr(pointer p) : ptr_(p) {}
354 unique_ptr(pointer p, typename if_<
355 boost::is_reference<D>,
357 typename detail::add_reference<const D>::type>::type d)
358 : ptr_(p, d) {}
359 unique_ptr(const unique_ptr& u)
360 : ptr_(const_cast<unique_ptr&>(u).release(), u.get_deleter()) {}
362 // destructor
363 ~unique_ptr() {reset();}
365 // assignment
366 unique_ptr& operator=(const unique_ptr& cu)
368 unique_ptr& u = const_cast<unique_ptr&>(cu);
369 reset(u.release());
370 ptr_.second() = u.get_deleter();
371 return *this;
373 unique_ptr& operator=(int nat::*)
375 reset();
376 return *this;
379 // observers
380 typename detail::add_reference<T>::type operator[](std::size_t i) const {return ptr_.first()[i];}
381 pointer get() const {return ptr_.first();}
382 deleter_reference get_deleter() {return ptr_.second();}
383 deleter_const_reference get_deleter() const {return ptr_.second();}
384 operator int nat::*() const {return ptr_.first() ? &nat::for_bool_ : 0;}
386 // modifiers
387 pointer release()
389 pointer tmp = ptr_.first();
390 ptr_.first() = 0;
391 return tmp;
393 void reset(pointer p = 0)
395 if (ptr_.first() != p)
397 if (ptr_.first())
398 ptr_.second()(ptr_.first());
399 ptr_.first() = p;
402 void swap(unique_ptr& u) {ptr_.swap(u.ptr_);}
403 private:
404 boost::compressed_pair<pointer, D> ptr_;
406 template <class U, class E> unique_ptr(U p, E,
407 typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0);
408 template <class U> explicit unique_ptr(U,
409 typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0);
411 unique_ptr(unique_ptr&);
412 template <class U> unique_ptr(U&, typename detail::unique_ptr_error<U>::type = 0);
414 unique_ptr& operator=(unique_ptr&);
415 template <class U> typename detail::unique_ptr_error<U>::type operator=(U&);
418 template <class T, class D, std::size_t N>
419 class unique_ptr<T[N], D>
421 struct nat {int for_bool_;};
422 typedef typename detail::add_reference<D>::type deleter_reference;
423 typedef typename detail::add_reference<const D>::type deleter_const_reference;
424 public:
425 typedef T element_type;
426 typedef D deleter_type;
427 typedef typename detail::pointer_type<T, D>::type pointer;
428 static const std::size_t size = N;
430 // constructors
431 unique_ptr() : ptr_(0) {}
432 explicit unique_ptr(pointer p) : ptr_(p) {}
433 unique_ptr(pointer p, typename if_<
434 boost::is_reference<D>,
436 typename detail::add_reference<const D>::type>::type d)
437 : ptr_(p, d) {}
438 unique_ptr(const unique_ptr& u)
439 : ptr_(const_cast<unique_ptr&>(u).release(), u.get_deleter()) {}
441 // destructor
442 ~unique_ptr() {reset();}
444 // assignment
445 unique_ptr& operator=(const unique_ptr& cu)
447 unique_ptr& u = const_cast<unique_ptr&>(cu);
448 reset(u.release());
449 ptr_.second() = u.get_deleter();
450 return *this;
452 unique_ptr& operator=(int nat::*)
454 reset();
455 return *this;
458 // observers
459 typename detail::add_reference<T>::type operator[](std::size_t i) const {return ptr_.first()[i];}
460 pointer get() const {return ptr_.first();}
461 deleter_reference get_deleter() {return ptr_.second();}
462 deleter_const_reference get_deleter() const {return ptr_.second();}
463 operator int nat::*() const {return ptr_.first() ? &nat::for_bool_ : 0;}
465 // modifiers
466 pointer release()
468 pointer tmp = ptr_.first();
469 ptr_.first() = 0;
470 return tmp;
472 void reset(pointer p = 0)
474 if (ptr_.first() != p)
476 if (ptr_.first())
477 ptr_.second()(ptr_.first(), N);
478 ptr_.first() = p;
481 void swap(unique_ptr& u) {ptr_.swap(u.ptr_);}
482 private:
483 boost::compressed_pair<pointer, D> ptr_;
485 template <class U, class E> unique_ptr(U p, E,
486 typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0);
487 template <class U> explicit unique_ptr(U,
488 typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0);
490 unique_ptr(unique_ptr&);
491 template <class U> unique_ptr(U&, typename detail::unique_ptr_error<U>::type = 0);
493 unique_ptr& operator=(unique_ptr&);
494 template <class U> typename detail::unique_ptr_error<U>::type operator=(U&);
497 template <class T, class D> inline
498 void swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y)
499 { x.swap(y); }
501 template <class T1, class D1, class T2, class D2> inline
502 bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
503 { return x.get() == y.get(); }
505 template <class T1, class D1, class T2, class D2> inline
506 bool operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
507 { return x.get() != y.get(); }
509 template <class T1, class D1, class T2, class D2> inline
510 bool operator <(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
511 { return x.get() < y.get(); }
513 template <class T1, class D1, class T2, class D2> inline
514 bool operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
515 { return x.get() <= y.get(); }
517 template <class T1, class D1, class T2, class D2> inline
518 bool operator >(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
519 { return x.get() > y.get(); }
521 template <class T1, class D1, class T2, class D2> inline
522 bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
523 { return x.get() >= y.get(); }
526 //!Returns the type of a unique pointer
527 //!of type T with boost::interprocess::deleter deleter
528 //!that can be constructed in the given managed segment type.
529 template<class T, class ManagedMemory>
530 struct managed_unique_ptr
532 typedef unique_ptr
534 , typename ManagedMemory::template deleter<T>::type
535 > type;
538 //!Returns an instance of a unique pointer constructed
539 //!with boost::interproces::deleter from a pointer
540 //!of type T that has been allocated in the passed managed segment
541 template<class T, class ManagedMemory>
542 inline typename managed_unique_ptr<T, ManagedMemory>::type
543 make_managed_unique_ptr(T *constructed_object, ManagedMemory &managed_memory)
545 return typename managed_unique_ptr<T, ManagedMemory>::type
546 (constructed_object, managed_memory.template get_deleter<T>());
549 } //namespace interprocess{
550 } //namespace boost{
552 #include <boost/interprocess/detail/config_end.hpp>
554 #endif //#ifndef BOOST_INTERPROCESS_UNIQUE_PTR_HPP_INCLUDED