• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright 2007, 2008 Steven Watanabe, Joseph Gauterin, Niels Dekker
4 // (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
5 // Software License, Version 1.0. (See accompanying file
6 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // See http://www.boost.org/libs/container for documentation.
9 //
10 //////////////////////////////////////////////////////////////////////////////
11 
12 #ifndef BOOST_MOVE_ADL_MOVE_SWAP_HPP
13 #define BOOST_MOVE_ADL_MOVE_SWAP_HPP
14 
15 #ifndef BOOST_CONFIG_HPP
16 #  include <boost/config.hpp>
17 #endif
18 #
19 #if defined(BOOST_HAS_PRAGMA_ONCE)
20 #  pragma once
21 #endif
22 
23 //Based on Boost.Core's swap.
24 //Many thanks to Steven Watanabe, Joseph Gauterin and Niels Dekker.
25 #include <cstddef> //for std::size_t
26 #include <boost/move/detail/workaround.hpp>  //forceinline
27 
28 //Try to avoid including <algorithm>, as it's quite big
29 #if defined(_MSC_VER) && defined(BOOST_DINKUMWARE_STDLIB)
30    #include <utility>   //Dinkum libraries define std::swap in utility which is lighter than algorithm
31 #elif defined(BOOST_GNU_STDLIB)
32    //For non-GCC compilers, where GNUC version is not very reliable, or old GCC versions
33    //use the good old stl_algobase header, which is quite lightweight
34    #if !defined(BOOST_GCC) || ((__GNUC__ < 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ < 3)))
35       #include <bits/stl_algobase.h>
36    #elif (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
37       //In GCC 4.3 a tiny stl_move.h was created with swap and move utilities
38       #include <bits/stl_move.h>
39    #else
40       //In GCC 4.4 stl_move.h was renamed to move.h
41       #include <bits/move.h>
42    #endif
43 #elif defined(_LIBCPP_VERSION)
44    #include <type_traits>  //The initial import of libc++ defines std::swap and still there
45 #elif __cplusplus >= 201103L
46    #include <utility>    //Fallback for C++ >= 2011
47 #else
48    #include <algorithm>  //Fallback for C++98/03
49 #endif
50 
51 #include <boost/move/utility_core.hpp> //for boost::move
52 
53 #if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
54 
55 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
56 namespace boost_move_member_swap {
57 
58 struct dont_care
59 {
60    dont_care(...);
61 };
62 
63 struct private_type
64 {
65    static private_type p;
66    private_type const &operator,(int) const;
67 };
68 
69 typedef char yes_type;
70 struct no_type{ char dummy[2]; };
71 
72 template<typename T>
73 no_type is_private_type(T const &);
74 
75 yes_type is_private_type(private_type const &);
76 
77 template <typename Type>
78 class has_member_function_named_swap
79 {
80    struct BaseMixin
81    {
82       void swap();
83    };
84 
85    struct Base : public Type, public BaseMixin { Base(); };
86    template <typename T, T t> class Helper{};
87 
88    template <typename U>
89    static no_type deduce(U*, Helper<void (BaseMixin::*)(), &U::swap>* = 0);
90    static yes_type deduce(...);
91 
92    public:
93    static const bool value = sizeof(yes_type) == sizeof(deduce((Base*)(0)));
94 };
95 
96 template<typename Fun, bool HasFunc>
97 struct has_member_swap_impl
98 {
99    static const bool value = false;
100 };
101 
102 template<typename Fun>
103 struct has_member_swap_impl<Fun, true>
104 {
105    struct FunWrap : Fun
106    {
107       FunWrap();
108 
109       using Fun::swap;
110       private_type swap(dont_care) const;
111    };
112 
113    static Fun &declval_fun();
114    static FunWrap declval_wrap();
115 
116    static bool const value =
117       sizeof(no_type) == sizeof(is_private_type( (declval_wrap().swap(declval_fun()), 0)) );
118 };
119 
120 template<typename Fun>
121 struct has_member_swap : public has_member_swap_impl
122       <Fun, has_member_function_named_swap<Fun>::value>
123 {};
124 
125 }  //namespace boost_move_member_swap
126 
127 namespace boost_move_adl_swap{
128 
129 template<class P1, class P2, bool = P1::value>
130 struct and_op_impl
131 {  static const bool value = false; };
132 
133 template<class P1, class P2>
134 struct and_op_impl<P1, P2, true>
135 {  static const bool value = P2::value;   };
136 
137 template<class P1, class P2>
138 struct and_op
139    : and_op_impl<P1, P2>
140 {};
141 
142 //////
143 
144 template<class P1, class P2, bool = P1::value>
145 struct and_op_not_impl
146 {  static const bool value = false; };
147 
148 template<class P1, class P2>
149 struct and_op_not_impl<P1, P2, true>
150 {  static const bool value = !P2::value;   };
151 
152 template<class P1, class P2>
153 struct and_op_not
154    : and_op_not_impl<P1, P2>
155 {};
156 
157 template<class T>
swap_proxy(T & x,T & y,typename boost::move_detail::enable_if_c<!boost::move_detail::has_move_emulation_enabled_impl<T>::value>::type * =0)158 BOOST_MOVE_FORCEINLINE void swap_proxy(T& x, T& y, typename boost::move_detail::enable_if_c<!boost::move_detail::has_move_emulation_enabled_impl<T>::value>::type* = 0)
159 {
160    //use std::swap if argument dependent lookup fails
161    //Use using directive ("using namespace xxx;") instead as some older compilers
162    //don't do ADL with using declarations ("using ns::func;").
163    using namespace std;
164    swap(x, y);
165 }
166 
167 template<class T>
swap_proxy(T & x,T & y,typename boost::move_detail::enable_if<and_op_not_impl<boost::move_detail::has_move_emulation_enabled_impl<T>,boost_move_member_swap::has_member_swap<T>>>::type * =0)168 BOOST_MOVE_FORCEINLINE void swap_proxy(T& x, T& y
169                , typename boost::move_detail::enable_if< and_op_not_impl<boost::move_detail::has_move_emulation_enabled_impl<T>
170                                                                         , boost_move_member_swap::has_member_swap<T> >
171                                                        >::type* = 0)
172 {  T t(::boost::move(x)); x = ::boost::move(y); y = ::boost::move(t);  }
173 
174 template<class T>
swap_proxy(T & x,T & y,typename boost::move_detail::enable_if<and_op_impl<boost::move_detail::has_move_emulation_enabled_impl<T>,boost_move_member_swap::has_member_swap<T>>>::type * =0)175 BOOST_MOVE_FORCEINLINE void swap_proxy(T& x, T& y
176                , typename boost::move_detail::enable_if< and_op_impl< boost::move_detail::has_move_emulation_enabled_impl<T>
177                                                                     , boost_move_member_swap::has_member_swap<T> >
178                                                        >::type* = 0)
179 {  x.swap(y);  }
180 
181 }  //namespace boost_move_adl_swap{
182 
183 #else
184 
185 namespace boost_move_adl_swap{
186 
187 template<class T>
swap_proxy(T & x,T & y)188 BOOST_MOVE_FORCEINLINE void swap_proxy(T& x, T& y)
189 {
190    using std::swap;
191    swap(x, y);
192 }
193 
194 }  //namespace boost_move_adl_swap{
195 
196 #endif   //#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
197 
198 namespace boost_move_adl_swap{
199 
200 template<class T, std::size_t N>
swap_proxy(T (& x)[N],T (& y)[N])201 void swap_proxy(T (& x)[N], T (& y)[N])
202 {
203    for (std::size_t i = 0; i < N; ++i){
204       ::boost_move_adl_swap::swap_proxy(x[i], y[i]);
205    }
206 }
207 
208 }  //namespace boost_move_adl_swap {
209 
210 #endif   //!defined(BOOST_MOVE_DOXYGEN_INVOKED)
211 
212 namespace boost{
213 
214 //! Exchanges the values of a and b, using Argument Dependent Lookup (ADL) to select a
215 //! specialized swap function if available. If no specialized swap function is available,
216 //! std::swap is used.
217 //!
218 //! <b>Exception</b>: If T uses Boost.Move's move emulation and the compiler has
219 //! no rvalue references then:
220 //!
221 //!   -  If T has a <code>T::swap(T&)</code> member, that member is called.
222 //!   -  Otherwise a move-based swap is called, equivalent to:
223 //!      <code>T t(::boost::move(x)); x = ::boost::move(y); y = ::boost::move(t);</code>.
224 template<class T>
adl_move_swap(T & x,T & y)225 BOOST_MOVE_FORCEINLINE void adl_move_swap(T& x, T& y)
226 {
227    ::boost_move_adl_swap::swap_proxy(x, y);
228 }
229 
230 //! Exchanges elements between range [first1, last1) and another range starting at first2
231 //! using boost::adl_move_swap.
232 //!
233 //! Parameters:
234 //!   first1, last1   -   the first range of elements to swap
235 //!   first2   -   beginning of the second range of elements to swap
236 //!
237 //! Type requirements:
238 //!   - ForwardIt1, ForwardIt2 must meet the requirements of ForwardIterator.
239 //!   - The types of dereferenced ForwardIt1 and ForwardIt2 must meet the
240 //!     requirements of Swappable
241 //!
242 //! Return value: Iterator to the element past the last element exchanged in the range
243 //! beginning with first2.
244 template<class ForwardIt1, class ForwardIt2>
adl_move_swap_ranges(ForwardIt1 first1,ForwardIt1 last1,ForwardIt2 first2)245 ForwardIt2 adl_move_swap_ranges(ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2)
246 {
247     while (first1 != last1) {
248       ::boost::adl_move_swap(*first1, *first2);
249       ++first1;
250       ++first2;
251     }
252    return first2;
253 }
254 
255 template<class BidirIt1, class BidirIt2>
adl_move_swap_ranges_backward(BidirIt1 first1,BidirIt1 last1,BidirIt2 last2)256 BidirIt2 adl_move_swap_ranges_backward(BidirIt1 first1, BidirIt1 last1, BidirIt2 last2)
257 {
258    while (first1 != last1) {
259       ::boost::adl_move_swap(*(--last1), *(--last2));
260    }
261    return last2;
262 }
263 
264 template<class ForwardIt1, class ForwardIt2>
adl_move_iter_swap(ForwardIt1 a,ForwardIt2 b)265 void adl_move_iter_swap(ForwardIt1 a, ForwardIt2 b)
266 {
267    boost::adl_move_swap(*a, *b);
268 }
269 
270 }  //namespace boost{
271 
272 #endif   //#ifndef BOOST_MOVE_ADL_MOVE_SWAP_HPP
273