1 //////////////////////////////////////////////////////////////////////////////
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)
8 // See http://www.boost.org/libs/move for documentation.
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 //////////////////////////////////////////////////////////////////////////////
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>
34 namespace interprocess
{
35 namespace move_detail
{
43 template <class T
, class U
>
47 class false_t
{ char dummy
[2]; };
48 static true_t
dispatch(U
);
49 static false_t
dispatch(...);
52 enum { value
= sizeof(dispatch(trigger())) == sizeof(true_t
) };
55 } //namespace move_detail {
56 } //namespace interprocess {
59 #if !defined(BOOST_HAS_RVALUE_REFS) && !defined(BOOST_MOVE_DOXYGEN_INVOKED)
62 namespace interprocess
{
64 //////////////////////////////////////////////////////////////////////////////
68 //////////////////////////////////////////////////////////////////////////////
75 void operator=(rv
const&);
78 //T &get() { return *this; }
81 //////////////////////////////////////////////////////////////////////////////
85 //////////////////////////////////////////////////////////////////////////////
87 namespace move_detail
{
92 static const bool value
= false;
98 static const bool value
= true;
101 } //namespace move_detail {
103 //////////////////////////////////////////////////////////////////////////////
107 //////////////////////////////////////////////////////////////////////////////
112 static const bool value
= move_detail::is_convertible
<T
, rv
<T
>&>::value
;
116 class is_movable
< rv
<T
> >
119 static const bool value
= false;
122 //////////////////////////////////////////////////////////////////////////////
126 //////////////////////////////////////////////////////////////////////////////
128 typename
boost::disable_if
<is_movable
<T
>, T
&>::type
move(T
& x
)
134 typename enable_if
<is_movable
<T
>, rv
<T
>&>::type
move(T
& x
)
136 return reinterpret_cast<rv
<T
>& >(x
);
140 typename enable_if
<is_movable
<T
>, rv
<T
>&>::type
move(const rv
<T
>& x
)
142 return const_cast<rv
<T
>& >(x
);
145 //////////////////////////////////////////////////////////////////////////////
149 //////////////////////////////////////////////////////////////////////////////
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
);
160 typename enable_if<boost::interprocess::move_detail::is_rv<T>, T &>::type
161 forward(typename move_detail::identity<T>::type &x)
167 typename disable_if<boost::interprocess::move_detail::is_rv<T>, T &>::type
168 forward(typename move_detail::identity<T>::type &x)
174 typename disable_if
<boost::interprocess::move_detail::is_rv
<T
>, const T
&>::type
175 forward(const typename
move_detail::identity
<T
>::type
&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)\
206 } //namespace interprocess {
209 #else //BOOST_HAS_RVALUE_REFS
211 #include <boost/type_traits/remove_reference.hpp>
214 namespace interprocess
{
216 //////////////////////////////////////////////////////////////////////////////
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>
230 static const bool value
= move_detail::is_convertible
<T
&&, T
>::value
;
233 //////////////////////////////////////////////////////////////////////////////
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
);
247 template <class T
> inline
248 typename remove_reference
<T
>::type
&& move(T
&& t
)
252 //////////////////////////////////////////////////////////////////////////////
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.
267 //! * If input_reference binds to const boost::interprocess::rv<T> & then it output_reference is
270 //! * Else, input_reference is equal to output_reference is equal to input_reference.
271 template <class T
> inline output_reference
forward(input_reference
);
273 template <class T
> inline
274 T
&& forward (typename
move_detail::identity
<T
>::type
&& t
)
278 //////////////////////////////////////////////////////////////////////////////
280 // BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION
282 //////////////////////////////////////////////////////////////////////////////
284 //! This macro expands to nothing for compilers with rvalue references.
285 //! Otherwise expands to:
287 //! operator boost::interprocess::rv<TYPE>&()
288 //! { return static_cast<boost::interprocess::rv<TYPE>& >(*this); }
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)\
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)\
313 } //namespace interprocess {
314 } //namespace boost {
316 #endif //BOOST_HAS_RVALUE_REFS
319 namespace interprocess
{
321 //////////////////////////////////////////////////////////////////////////////
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.
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
;
341 typedef typename
boost::mpl::if_
342 < boost::interprocess::is_movable
<value_type
>
343 , boost::interprocess::rv
<value_type
>&
344 , value_type
& >::type reference
;
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
;
353 explicit move_iterator(It i
)
358 move_iterator(const move_iterator
<U
>& u
)
362 iterator_type
base() const
365 reference
operator*() const
367 #if defined(BOOST_HAS_RVALUE_REFS)
370 return boost::interprocess::move(*m_it
);
374 pointer
operator->() const
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)
406 return boost::interprocess::move(m_it
[n
]);
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
); }
440 namespace move_detail
{
443 struct is_move_iterator
445 static const bool value
= false;
449 struct is_move_iterator
< ::boost::interprocess::move_iterator
<I
> >
451 static const bool value
= true;
454 } //namespace move_detail {
456 //////////////////////////////////////////////////////////////////////////////
460 //////////////////////////////////////////////////////////////////////////////
463 //! <b>Returns</b>: move_iterator<It>(i).
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>
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>
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>
549 typename
C::iterator pos_
;
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
));
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 //////////////////////////////////////////////////////////////////////////////
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
)
599 *result
= boost::interprocess::move(*f
);
605 //////////////////////////////////////////////////////////////////////////////
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
)
627 *result
= boost::interprocess::move(*l
);
632 //////////////////////////////////////////////////////////////////////////////
634 // uninitialized_move
636 //////////////////////////////////////////////////////////////////////////////
640 //! for (; first != last; ++result, ++first)
641 //! new (static_cast<void*>(&*result))
642 //! typename iterator_traits<ForwardIterator>::value_type(boost::interprocess::move(*first));
645 //! <b>Returns</b>: result
647 <typename I
, // I models InputIterator
648 typename F
> // F models ForwardIterator
649 F
uninitialized_move(I f
, I l
, F r
651 ,typename enable_if
<is_movable
<typename
std::iterator_traits
<I
>::value_type
> >::type
* = 0
655 typedef typename
std::iterator_traits
<I
>::value_type input_value_type
;
657 ::new(static_cast<void*>(&*r
)) input_value_type(boost::interprocess::move(*f
));
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
{
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
);
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 {
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
);
715 //! for (; first != last; ++result, ++first)
716 //! new (static_cast<void*>(&*result))
717 //! typename iterator_traits<ForwardIterator>::value_type(*first);
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>
726 <typename I
, // I models InputIterator
727 typename F
> // F models ForwardIterator
728 F
uninitialized_copy_or_move(I f
, I l
, F r
730 ,typename disable_if
< move_detail::is_move_iterator
<I
> >::type
* = 0
734 return std::uninitialized_copy(f
, l
, r
);
737 ///has_trivial_destructor_after_move<> == true_type
738 ///specialization for optimizations
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