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 
26 #include <boost/config.hpp>
27 #include <cstddef> //for std::size_t
28 
29 //Try to avoid including <algorithm>, as it's quite big
30 #if defined(_MSC_VER) && defined(BOOST_DINKUMWARE_STDLIB)
31    #include <utility>   //Dinkum libraries define std::swap in utility which is lighter than algorithm
32 #elif defined(BOOST_GNU_STDLIB)
33    //For non-GCC compilers, where GNUC version is not very reliable, or old GCC versions
34    //use the good old stl_algobase header, which is quite lightweight
35    #if !defined(BOOST_GCC) || ((__GNUC__ < 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ < 3)))
36       #include <bits/stl_algobase.h>
37    #elif (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
38       //In GCC 4.3 a tiny stl_move.h was created with swap and move utilities
39       #include <bits/stl_move.h>
40    #else
41       //In GCC 4.4 stl_move.h was renamed to move.h
42       #include <bits/move.h>
43    #endif
44 #elif defined(_LIBCPP_VERSION)
45    #include <type_traits>  //The initial import of libc++ defines std::swap and still there
46 #elif __cplusplus >= 201103L
47    #include <utility>    //Fallback for C++ >= 2011
48 #else
49    #include <algorithm>  //Fallback for C++98/03
50 #endif
51 
52 #include <boost/move/utility_core.hpp> //for boost::move
53 
54 #if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
55 
56 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
57 namespace boost_move_member_swap {
58 
59 struct dont_care
60 {
61    dont_care(...);
62 };
63 
64 struct private_type
65 {
66    static private_type p;
67    private_type const &operator,(int) const;
68 };
69 
70 typedef char yes_type;
71 struct no_type{ char dummy[2]; };
72 
73 template<typename T>
74 no_type is_private_type(T const &);
75 
76 yes_type is_private_type(private_type const &);
77 
78 template <typename Type>
79 class has_member_function_named_swap
80 {
81    struct BaseMixin
82    {
83       void swap();
84    };
85 
86    struct Base : public Type, public BaseMixin { Base(); };
87    template <typename T, T t> class Helper{};
88 
89    template <typename U>
90    static no_type deduce(U*, Helper<void (BaseMixin::*)(), &U::swap>* = 0);
91    static yes_type deduce(...);
92 
93    public:
94    static const bool value = sizeof(yes_type) == sizeof(deduce((Base*)(0)));
95 };
96 
97 template<typename Fun, bool HasFunc>
98 struct has_member_swap_impl
99 {
100    static const bool value = false;
101 };
102 
103 template<typename Fun>
104 struct has_member_swap_impl<Fun, true>
105 {
106    struct FunWrap : Fun
107    {
108       FunWrap();
109 
110       using Fun::swap;
111       private_type swap(dont_care) const;
112    };
113 
114    static Fun &declval_fun();
115    static FunWrap declval_wrap();
116 
117    static bool const value =
118       sizeof(no_type) == sizeof(is_private_type( (declval_wrap().swap(declval_fun()), 0)) );
119 };
120 
121 template<typename Fun>
122 struct has_member_swap : public has_member_swap_impl
123       <Fun, has_member_function_named_swap<Fun>::value>
124 {};
125 
126 }  //namespace boost_move_member_swap
127 
128 namespace boost_move_adl_swap{
129 
130 template<class P1, class P2, bool = P1::value>
131 struct and_op_impl
132 {  static const bool value = false; };
133 
134 template<class P1, class P2>
135 struct and_op_impl<P1, P2, true>
136 {  static const bool value = P2::value;   };
137 
138 template<class P1, class P2>
139 struct and_op
140    : and_op_impl<P1, P2>
141 {};
142 
143 //////
144 
145 template<class P1, class P2, bool = P1::value>
146 struct and_op_not_impl
147 {  static const bool value = false; };
148 
149 template<class P1, class P2>
150 struct and_op_not_impl<P1, P2, true>
151 {  static const bool value = !P2::value;   };
152 
153 template<class P1, class P2>
154 struct and_op_not
155    : and_op_not_impl<P1, P2>
156 {};
157 
158 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)159 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)
160 {
161    //use std::swap if argument dependent lookup fails
162    //Use using directive ("using namespace xxx;") instead as some older compilers
163    //don't do ADL with using declarations ("using ns::func;").
164    using namespace std;
165    swap(x, y);
166 }
167 
168 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)169 void swap_proxy(T& x, T& y
170                , typename boost::move_detail::enable_if< and_op_not_impl<boost::move_detail::has_move_emulation_enabled_impl<T>
171                                                                         , boost_move_member_swap::has_member_swap<T> >
172                                                        >::type* = 0)
173 {  T t(::boost::move(x)); x = ::boost::move(y); y = ::boost::move(t);  }
174 
175 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)176 void swap_proxy(T& x, T& y
177                , typename boost::move_detail::enable_if< and_op_impl< boost::move_detail::has_move_emulation_enabled_impl<T>
178                                                                     , boost_move_member_swap::has_member_swap<T> >
179                                                        >::type* = 0)
180 {  x.swap(y);  }
181 
182 }  //namespace boost_move_adl_swap{
183 
184 #else
185 
186 namespace boost_move_adl_swap{
187 
188 template<class T>
swap_proxy(T & x,T & y)189 void swap_proxy(T& x, T& y)
190 {
191    using std::swap;
192    swap(x, y);
193 }
194 
195 }  //namespace boost_move_adl_swap{
196 
197 #endif   //#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
198 
199 namespace boost_move_adl_swap{
200 
201 template<class T, std::size_t N>
swap_proxy(T (& x)[N],T (& y)[N])202 void swap_proxy(T (& x)[N], T (& y)[N])
203 {
204    for (std::size_t i = 0; i < N; ++i){
205       ::boost_move_adl_swap::swap_proxy(x[i], y[i]);
206    }
207 }
208 
209 }  //namespace boost_move_adl_swap {
210 
211 #endif   //!defined(BOOST_MOVE_DOXYGEN_INVOKED)
212 
213 namespace boost{
214 
215 //! Exchanges the values of a and b, using Argument Dependent Lookup (ADL) to select a
216 //! specialized swap function if available. If no specialized swap function is available,
217 //! std::swap is used.
218 //!
219 //! <b>Exception</b>: If T uses Boost.Move's move emulation and the compiler has
220 //! no rvalue references then:
221 //!
222 //!   -  If T has a <code>T::swap(T&)</code> member, that member is called.
223 //!   -  Otherwise a move-based swap is called, equivalent to:
224 //!      <code>T t(::boost::move(x)); x = ::boost::move(y); y = ::boost::move(t);</code>.
225 template<class T>
adl_move_swap(T & x,T & y)226 void adl_move_swap(T& x, T& y)
227 {
228    ::boost_move_adl_swap::swap_proxy(x, y);
229 }
230 
231 }  //namespace boost{
232 
233 #endif   //#ifndef BOOST_MOVE_ADL_MOVE_SWAP_HPP
234