]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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> | |
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> | |
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> | |
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> | |
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> | |
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> | |
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> | |
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> | |
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 | } //namespace boost{ | |
265 | ||
266 | #endif //#ifndef BOOST_MOVE_ADL_MOVE_SWAP_HPP |