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