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