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)
56namespace boost_move_member_swap {
57
58struct dont_care
59{
60 dont_care(...);
61};
62
63struct private_type
64{
65 static private_type p;
66 private_type const &operator,(int) const;
67};
68
69typedef char yes_type;
70struct no_type{ char dummy[2]; };
71
72template<typename T>
73no_type is_private_type(T const &);
74
75yes_type is_private_type(private_type const &);
76
77template <typename Type>
78class 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
96template<typename Fun, bool HasFunc>
97struct has_member_swap_impl
98{
99 static const bool value = false;
100};
101
102template<typename Fun>
103struct 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
120template<typename Fun>
121struct 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
127namespace boost_move_adl_swap{
128
129template<class P1, class P2, bool = P1::value>
130struct and_op_impl
131{ static const bool value = false; };
132
133template<class P1, class P2>
134struct and_op_impl<P1, P2, true>
135{ static const bool value = P2::value; };
136
137template<class P1, class P2>
138struct and_op
139 : and_op_impl<P1, P2>
140{};
141
142//////
143
144template<class P1, class P2, bool = P1::value>
145struct and_op_not_impl
146{ static const bool value = false; };
147
148template<class P1, class P2>
149struct and_op_not_impl<P1, P2, true>
150{ static const bool value = !P2::value; };
151
152template<class P1, class P2>
153struct and_op_not
154 : and_op_not_impl<P1, P2>
155{};
156
157template<class T>
158BOOST_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
167template<class T>
168BOOST_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
174template<class T>
175BOOST_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
185namespace boost_move_adl_swap{
186
187template<class T>
188BOOST_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
198namespace boost_move_adl_swap{
199
200template<class T, std::size_t N>
201void 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
212namespace 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>.
224template<class T>
225BOOST_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.
244template<class ForwardIt1, class ForwardIt2>
245ForwardIt2 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
255template<class BidirIt1, class BidirIt2>
256BidirIt2 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
264template<class ForwardIt1, class ForwardIt2>
265void 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

source code of include/boost/move/adl_move_swap.hpp