adl_move_swap.hpp 7.9 KB

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