| 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 | 
| 267 |  |