fix doc example typo
[boost.git] / boost / interprocess / detail / move.hpp
blob9ecd69f70381333ec512e72644b5e9256886fbf4
1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright David Abrahams, Vicente Botet, Ion Gaztanaga 2009.
4 // Distributed under the Boost Software License, Version 1.0.
5 // (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // See http://www.boost.org/libs/move for documentation.
9 //
10 //////////////////////////////////////////////////////////////////////////////
12 // Parts of this file come from Adobe's Move library:
14 // Copyright 2005-2007 Adobe Systems Incorporated
15 // Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
16 // or a copy at http://stlab.adobe.com/licenses.html)
18 //////////////////////////////////////////////////////////////////////////////
20 //! \file
22 #ifndef BOOST_INTERPROCESS_MOVE_HPP
23 #define BOOST_INTERPROCESS_MOVE_HPP
25 #include <boost/config.hpp>
26 #include <algorithm> //copy, copy_backward
27 #include <memory> //uninitialized_copy
28 #include <iterator> //std::iterator
29 #include <boost/mpl/if.hpp>
30 #include <boost/utility/enable_if.hpp>
31 #include <boost/type_traits/has_trivial_destructor.hpp>
33 namespace boost {
34 namespace interprocess {
35 namespace move_detail {
37 template <class T>
38 struct identity
40 typedef T type;
43 template <class T, class U>
44 class is_convertible
46 typedef char true_t;
47 class false_t { char dummy[2]; };
48 static true_t dispatch(U);
49 static false_t dispatch(...);
50 static T trigger();
51 public:
52 enum { value = sizeof(dispatch(trigger())) == sizeof(true_t) };
55 } //namespace move_detail {
56 } //namespace interprocess {
57 } //namespace boost {
59 #if !defined(BOOST_HAS_RVALUE_REFS) && !defined(BOOST_MOVE_DOXYGEN_INVOKED)
61 namespace boost {
62 namespace interprocess {
64 //////////////////////////////////////////////////////////////////////////////
66 // struct rv
68 //////////////////////////////////////////////////////////////////////////////
69 template <class T>
70 class rv : public T
72 rv();
73 ~rv();
74 rv(rv const&);
75 void operator=(rv const&);
77 public:
78 //T &get() { return *this; }
81 //////////////////////////////////////////////////////////////////////////////
83 // move_detail::is_rv
85 //////////////////////////////////////////////////////////////////////////////
87 namespace move_detail {
89 template <class T>
90 struct is_rv
92 static const bool value = false;
95 template <class T>
96 struct is_rv< rv<T> >
98 static const bool value = true;
101 } //namespace move_detail {
103 //////////////////////////////////////////////////////////////////////////////
105 // is_movable
107 //////////////////////////////////////////////////////////////////////////////
108 template<class T>
109 class is_movable
111 public:
112 static const bool value = move_detail::is_convertible<T, rv<T>&>::value;
115 template<class T>
116 class is_movable< rv<T> >
118 public:
119 static const bool value = false;
122 //////////////////////////////////////////////////////////////////////////////
124 // move()
126 //////////////////////////////////////////////////////////////////////////////
127 template <class T>
128 typename boost::disable_if<is_movable<T>, T&>::type move(T& x)
130 return x;
133 template <class T>
134 typename enable_if<is_movable<T>, rv<T>&>::type move(T& x)
136 return reinterpret_cast<rv<T>& >(x);
139 template <class T>
140 typename enable_if<is_movable<T>, rv<T>&>::type move(const rv<T>& x)
142 return const_cast<rv<T>& >(x);
145 //////////////////////////////////////////////////////////////////////////////
147 // forward()
149 //////////////////////////////////////////////////////////////////////////////
151 template <class T>
152 typename enable_if<boost::interprocess::move_detail::is_rv<T>, T &>::type
153 forward(const typename move_detail::identity<T>::type &x)
155 return const_cast<T&>(x);
159 template <class T>
160 typename enable_if<boost::interprocess::move_detail::is_rv<T>, T &>::type
161 forward(typename move_detail::identity<T>::type &x)
163 return x;
166 template <class T>
167 typename disable_if<boost::interprocess::move_detail::is_rv<T>, T &>::type
168 forward(typename move_detail::identity<T>::type &x)
170 return x;
173 template <class T>
174 typename disable_if<boost::interprocess::move_detail::is_rv<T>, const T &>::type
175 forward(const typename move_detail::identity<T>::type &x)
177 return x;
180 //////////////////////////////////////////////////////////////////////////////
182 // BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION
184 //////////////////////////////////////////////////////////////////////////////
185 #define BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(TYPE)\
186 operator boost::interprocess::rv<TYPE>&() \
187 { return reinterpret_cast<boost::interprocess::rv<TYPE>& >(*this); }\
191 #define BOOST_INTERPROCESS_RV_REF(TYPE)\
192 boost::interprocess::rv< TYPE >& \
195 #define BOOST_INTERPROCESS_RV_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\
196 boost::interprocess::rv< TYPE<ARG1, ARG2> >& \
199 #define BOOST_INTERPROCESS_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\
200 boost::interprocess::rv< TYPE<ARG1, ARG2, ARG3> >& \
203 #define BOOST_INTERPROCESS_FWD_REF(TYPE)\
204 const TYPE & \
206 } //namespace interprocess {
207 } //namespace boost
209 #else //BOOST_HAS_RVALUE_REFS
211 #include <boost/type_traits/remove_reference.hpp>
213 namespace boost {
214 namespace interprocess {
216 //////////////////////////////////////////////////////////////////////////////
218 // is_movable
220 //////////////////////////////////////////////////////////////////////////////
222 //! For compilers with rvalue references, this traits class returns true
223 //! if T && is convertible to T.
225 //! For other compilers returns true if T is convertible to <i>boost::interprocess::rv<T>&</i>
226 template<class T>
227 class is_movable
229 public:
230 static const bool value = move_detail::is_convertible<T&&, T>::value;
233 //////////////////////////////////////////////////////////////////////////////
235 // move
237 //////////////////////////////////////////////////////////////////////////////
240 #if defined(BOOST_MOVE_DOXYGEN_INVOKED)
241 //! This function provides a way to convert a reference into a rvalue reference
242 //! in compilers with rvalue reference. For other compilers converts T & into
243 //! <i>boost::interprocess::rv<T> &</i> so that move emulation is activated.
244 template <class T> inline
245 rvalue_reference move (input_reference);
246 #else
247 template <class T> inline
248 typename remove_reference<T>::type&& move(T&& t)
249 { return t; }
250 #endif
252 //////////////////////////////////////////////////////////////////////////////
254 // forward
256 //////////////////////////////////////////////////////////////////////////////
259 #if defined(BOOST_MOVE_DOXYGEN_INVOKED)
260 //! This function provides limited form of forwarding that is usually enough for
261 //! in-place construction and avoids the exponential overloading necessary for
262 //! perfect forwarding in C++03.
264 //! For compilers with rvalue references this function provides perfect forwarding.
266 //! Otherwise:
267 //! * If input_reference binds to const boost::interprocess::rv<T> & then it output_reference is
268 //! boost::rev<T> &
270 //! * Else, input_reference is equal to output_reference is equal to input_reference.
271 template <class T> inline output_reference forward(input_reference);
272 #else
273 template <class T> inline
274 T&& forward (typename move_detail::identity<T>::type&& t)
275 { return t; }
276 #endif
278 //////////////////////////////////////////////////////////////////////////////
280 // BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION
282 //////////////////////////////////////////////////////////////////////////////
284 //! This macro expands to nothing for compilers with rvalue references.
285 //! Otherwise expands to:
286 //! \code
287 //! operator boost::interprocess::rv<TYPE>&()
288 //! { return static_cast<boost::interprocess::rv<TYPE>& >(*this); }
289 //! \endcode
290 #define BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(TYPE)\
293 #define BOOST_INTERPROCESS_RV_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\
294 TYPE<ARG1, ARG2> && \
297 #define BOOST_INTERPROCESS_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\
298 TYPE<ARG1, ARG2, ARG3> && \
301 //! This macro expands to <i>T&&</i> for compilers with rvalue references.
302 //! Otherwise expands to <i>boost::interprocess::rv<T> &</i>.
303 #define BOOST_INTERPROCESS_RV_REF(TYPE)\
304 TYPE && \
307 //! This macro expands to <i>T&&</i> for compilers with rvalue references.
308 //! Otherwise expands to <i>const T &</i>.
309 #define BOOST_INTERPROCESS_FWD_REF(TYPE)\
310 TYPE && \
313 } //namespace interprocess {
314 } //namespace boost {
316 #endif //BOOST_HAS_RVALUE_REFS
318 namespace boost {
319 namespace interprocess {
321 //////////////////////////////////////////////////////////////////////////////
323 // move_iterator
325 //////////////////////////////////////////////////////////////////////////////
327 //! Class template move_iterator is an iterator adaptor with the same behavior
328 //! as the underlying iterator except that its dereference operator implicitly
329 //! converts the value returned by the underlying iterator's dereference operator
330 //! to an rvalue reference. Some generic algorithms can be called with move
331 //! iterators to replace copying with moving.
332 template <class It>
333 class move_iterator
335 public:
336 typedef It iterator_type;
337 typedef typename std::iterator_traits<iterator_type>::value_type value_type;
338 #if defined(BOOST_HAS_RVALUE_REFS) || defined(BOOST_MOVE_DOXYGEN_INVOKED)
339 typedef value_type && reference;
340 #else
341 typedef typename boost::mpl::if_
342 < boost::interprocess::is_movable<value_type>
343 , boost::interprocess::rv<value_type>&
344 , value_type & >::type reference;
345 #endif
346 typedef typename std::iterator_traits<iterator_type>::pointer pointer;
347 typedef typename std::iterator_traits<iterator_type>::difference_type difference_type;
348 typedef typename std::iterator_traits<iterator_type>::iterator_category iterator_category;
350 move_iterator()
353 explicit move_iterator(It i)
354 : m_it(i)
357 template <class U>
358 move_iterator(const move_iterator<U>& u)
359 : m_it(u.base())
362 iterator_type base() const
363 { return m_it; }
365 reference operator*() const
367 #if defined(BOOST_HAS_RVALUE_REFS)
368 return *m_it;
369 #else
370 return boost::interprocess::move(*m_it);
371 #endif
374 pointer operator->() const
375 { return m_it; }
377 move_iterator& operator++()
378 { ++m_it; return *this; }
380 move_iterator<iterator_type> operator++(int)
381 { move_iterator<iterator_type> tmp(*this); ++(*this); return tmp; }
383 move_iterator& operator--()
384 { --m_it; return *this; }
386 move_iterator<iterator_type> operator--(int)
387 { move_iterator<iterator_type> tmp(*this); --(*this); return tmp; }
389 move_iterator<iterator_type> operator+ (difference_type n) const
390 { return move_iterator<iterator_type>(m_it + n); }
392 move_iterator& operator+=(difference_type n)
393 { m_it += n; return *this; }
395 move_iterator<iterator_type> operator- (difference_type n) const
396 { return move_iterator<iterator_type>(m_it - n); }
398 move_iterator& operator-=(difference_type n)
399 { m_it -= n; return *this; }
401 reference operator[](difference_type n) const
403 #if defined(BOOST_HAS_RVALUE_REFS)
404 return m_it[n];
405 #else
406 return boost::interprocess::move(m_it[n]);
407 #endif
410 friend bool operator==(const move_iterator& x, const move_iterator& y)
411 { return x.base() == y.base(); }
413 friend bool operator!=(const move_iterator& x, const move_iterator& y)
414 { return x.base() != y.base(); }
416 friend bool operator< (const move_iterator& x, const move_iterator& y)
417 { return x.base() < y.base(); }
419 friend bool operator<=(const move_iterator& x, const move_iterator& y)
420 { return x.base() <= y.base(); }
422 friend bool operator> (const move_iterator& x, const move_iterator& y)
423 { return x.base() > y.base(); }
425 friend bool operator>=(const move_iterator& x, const move_iterator& y)
426 { return x.base() >= y.base(); }
428 friend difference_type operator-(const move_iterator& x, const move_iterator& y)
429 { return x.base() - y.base(); }
431 friend move_iterator operator+(difference_type n, const move_iterator& x)
432 { return move_iterator(x.base() + n); }
434 private:
435 It m_it;
439 //is_move_iterator
440 namespace move_detail {
442 template <class I>
443 struct is_move_iterator
445 static const bool value = false;
448 template <class I>
449 struct is_move_iterator< ::boost::interprocess::move_iterator<I> >
451 static const bool value = true;
454 } //namespace move_detail {
456 //////////////////////////////////////////////////////////////////////////////
458 // move_iterator
460 //////////////////////////////////////////////////////////////////////////////
463 //! <b>Returns</b>: move_iterator<It>(i).
464 template<class It>
465 move_iterator<It> make_move_iterator(const It &it)
466 { return move_iterator<It>(it); }
468 //////////////////////////////////////////////////////////////////////////////
470 // back_move_insert_iterator
472 //////////////////////////////////////////////////////////////////////////////
475 //! A move insert iterator that move constructs elements at the
476 //! back of a container
477 template <typename C> // C models Container
478 class back_move_insert_iterator
479 : public std::iterator<std::output_iterator_tag, void, void, void, void>
481 C* container_m;
483 public:
484 typedef C container_type;
486 explicit back_move_insert_iterator(C& x) : container_m(&x) { }
488 back_move_insert_iterator& operator=(typename C::reference x)
489 { container_m->push_back(boost::interprocess::move(x)); return *this; }
491 back_move_insert_iterator& operator*() { return *this; }
492 back_move_insert_iterator& operator++() { return *this; }
493 back_move_insert_iterator& operator++(int) { return *this; }
497 //! <b>Returns</b>: back_move_insert_iterator<C>(x).
498 template <typename C> // C models Container
499 inline back_move_insert_iterator<C> back_move_inserter(C& x)
501 return back_move_insert_iterator<C>(x);
504 //////////////////////////////////////////////////////////////////////////////
506 // front_move_insert_iterator
508 //////////////////////////////////////////////////////////////////////////////
510 //! A move insert iterator that move constructs elements int the
511 //! front of a container
512 template <typename C> // C models Container
513 class front_move_insert_iterator
514 : public std::iterator<std::output_iterator_tag, void, void, void, void>
516 C* container_m;
518 public:
519 typedef C container_type;
521 explicit front_move_insert_iterator(C& x) : container_m(&x) { }
523 front_move_insert_iterator& operator=(typename C::reference x)
524 { container_m->push_front(boost::interprocess::move(x)); return *this; }
526 front_move_insert_iterator& operator*() { return *this; }
527 front_move_insert_iterator& operator++() { return *this; }
528 front_move_insert_iterator& operator++(int) { return *this; }
532 //! <b>Returns</b>: front_move_insert_iterator<C>(x).
533 template <typename C> // C models Container
534 inline front_move_insert_iterator<C> front_move_inserter(C& x)
536 return front_move_insert_iterator<C>(x);
539 //////////////////////////////////////////////////////////////////////////////
541 // insert_move_iterator
543 //////////////////////////////////////////////////////////////////////////////
544 template <typename C> // C models Container
545 class move_insert_iterator
546 : public std::iterator<std::output_iterator_tag, void, void, void, void>
548 C* container_m;
549 typename C::iterator pos_;
551 public:
552 typedef C container_type;
554 explicit move_insert_iterator(C& x, typename C::iterator pos)
555 : container_m(&x), pos_(pos)
558 move_insert_iterator& operator=(typename C::reference x)
560 pos_ = container_m->insert(pos_, boost::interprocess::move(x));
561 ++pos_;
562 return *this;
565 move_insert_iterator& operator*() { return *this; }
566 move_insert_iterator& operator++() { return *this; }
567 move_insert_iterator& operator++(int) { return *this; }
571 //! <b>Returns</b>: move_insert_iterator<C>(x, it).
572 template <typename C> // C models Container
573 inline move_insert_iterator<C> move_inserter(C& x, typename C::iterator it)
575 return move_insert_iterator<C>(x, it);
578 //////////////////////////////////////////////////////////////////////////////
580 // move
582 //////////////////////////////////////////////////////////////////////////////
585 //! <b>Effects</b>: Moves elements in the range [first,last) into the range [result,result + (last -
586 //! first)) starting from first and proceeding to last. For each non-negative integer n < (last-first),
587 //! performs *(result + n) = boost::interprocess::move (*(first + n)).
589 //! <b>Effects</b>: result + (last - first).
591 //! <b>Requires</b>: result shall not be in the range [first,last).
593 //! <b>Complexity</b>: Exactly last - first move assignments.
594 template <typename I, // I models InputIterator
595 typename O> // O models OutputIterator
596 O move(I f, I l, O result)
598 while (f != l) {
599 *result = boost::interprocess::move(*f);
600 ++f; ++result;
602 return result;
605 //////////////////////////////////////////////////////////////////////////////
607 // move_backward
609 //////////////////////////////////////////////////////////////////////////////
611 //! <b>Effects</b>: Moves elements in the range [first,last) into the range
612 //! [result - (last-first),result) starting from last - 1 and proceeding to
613 //! first. For each positive integer n <= (last - first),
614 //! performs *(result - n) = boost::interprocess::move(*(last - n)).
616 //! <b>Requires</b>: result shall not be in the range [first,last).
618 //! <b>Returns</b>: result - (last - first).
620 //! <b>Complexity</b>: Exactly last - first assignments.
621 template <typename I, // I models BidirectionalIterator
622 typename O> // O models BidirectionalIterator
623 O move_backward(I f, I l, O result)
625 while (f != l) {
626 --l; --result;
627 *result = boost::interprocess::move(*l);
629 return result;
632 //////////////////////////////////////////////////////////////////////////////
634 // uninitialized_move
636 //////////////////////////////////////////////////////////////////////////////
638 //! <b>Effects</b>:
639 //! \code
640 //! for (; first != last; ++result, ++first)
641 //! new (static_cast<void*>(&*result))
642 //! typename iterator_traits<ForwardIterator>::value_type(boost::interprocess::move(*first));
643 //! \endcode
645 //! <b>Returns</b>: result
646 template
647 <typename I, // I models InputIterator
648 typename F> // F models ForwardIterator
649 F uninitialized_move(I f, I l, F r
650 /// @cond
651 ,typename enable_if<is_movable<typename std::iterator_traits<I>::value_type> >::type* = 0
652 /// @endcond
655 typedef typename std::iterator_traits<I>::value_type input_value_type;
656 while (f != l) {
657 ::new(static_cast<void*>(&*r)) input_value_type(boost::interprocess::move(*f));
658 ++f; ++r;
660 return r;
663 /// @cond
665 template
666 <typename I, // I models InputIterator
667 typename F> // F models ForwardIterator
668 F uninitialized_move(I f, I l, F r,
669 typename disable_if<is_movable<typename std::iterator_traits<I>::value_type> >::type* = 0)
671 return std::uninitialized_copy(f, l, r);
674 //////////////////////////////////////////////////////////////////////////////
676 // uninitialized_copy_or_move
678 //////////////////////////////////////////////////////////////////////////////
680 namespace move_detail {
682 template
683 <typename I, // I models InputIterator
684 typename F> // F models ForwardIterator
685 F uninitialized_move_move_iterator(I f, I l, F r,
686 typename enable_if< is_movable<typename I::value_type> >::type* = 0)
688 return boost::interprocess::uninitialized_move(f, l, r);
691 template
692 <typename I, // I models InputIterator
693 typename F> // F models ForwardIterator
694 F uninitialized_move_move_iterator(I f, I l, F r,
695 typename disable_if< is_movable<typename I::value_type> >::type* = 0)
697 return std::uninitialized_copy(f.base(), l.base(), r);
700 } //namespace move_detail {
702 template
703 <typename I, // I models InputIterator
704 typename F> // F models ForwardIterator
705 F uninitialized_copy_or_move(I f, I l, F r,
706 typename enable_if< move_detail::is_move_iterator<I> >::type* = 0)
708 return boost::interprocess::move_detail::uninitialized_move_move_iterator(f, l, r);
711 /// @endcond
713 //! <b>Effects</b>:
714 //! \code
715 //! for (; first != last; ++result, ++first)
716 //! new (static_cast<void*>(&*result))
717 //! typename iterator_traits<ForwardIterator>::value_type(*first);
718 //! \endcode
720 //! <b>Returns</b>: result
722 //! <b>Note</b>: This function is provided because
723 //! <i>std::uninitialized_copy</i> from some STL implementations
724 //! is not compatible with <i>move_iterator</i>
725 template
726 <typename I, // I models InputIterator
727 typename F> // F models ForwardIterator
728 F uninitialized_copy_or_move(I f, I l, F r
729 /// @cond
730 ,typename disable_if< move_detail::is_move_iterator<I> >::type* = 0
731 /// @endcond
734 return std::uninitialized_copy(f, l, r);
737 ///has_trivial_destructor_after_move<> == true_type
738 ///specialization for optimizations
739 template <class T>
740 struct has_trivial_destructor_after_move
741 : public boost::has_trivial_destructor<T>
744 } //namespace interprocess {
745 } //namespace boost {
747 #endif //#ifndef BOOST_INTERPROCESS_MOVE_HPP