adl_move_swap.hpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  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)
  40. #include <type_traits> //The initial import of libc++ defines std::swap and still there
  41. #elif __cplusplus >= 201103L
  42. #include <utility> //Fallback for C++ >= 2011
  43. #else
  44. #include <algorithm> //Fallback for C++98/03
  45. #endif
  46. #include <boost/move/utility_core.hpp> //for boost::move
  47. #if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
  48. #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  49. namespace boost_move_member_swap {
  50. struct dont_care
  51. {
  52. dont_care(...);
  53. };
  54. struct private_type
  55. {
  56. static private_type p;
  57. private_type const &operator,(int) const;
  58. };
  59. typedef char yes_type;
  60. struct no_type{ char dummy[2]; };
  61. template<typename T>
  62. no_type is_private_type(T const &);
  63. yes_type is_private_type(private_type const &);
  64. template <typename Type>
  65. class has_member_function_named_swap
  66. {
  67. struct BaseMixin
  68. {
  69. void swap();
  70. };
  71. struct Base : public Type, public BaseMixin { Base(); };
  72. template <typename T, T t> class Helper{};
  73. template <typename U>
  74. static no_type deduce(U*, Helper<void (BaseMixin::*)(), &U::swap>* = 0);
  75. static yes_type deduce(...);
  76. public:
  77. static const bool value = sizeof(yes_type) == sizeof(deduce((Base*)(0)));
  78. };
  79. template<typename Fun, bool HasFunc>
  80. struct has_member_swap_impl
  81. {
  82. static const bool value = false;
  83. };
  84. template<typename Fun>
  85. struct has_member_swap_impl<Fun, true>
  86. {
  87. struct FunWrap : Fun
  88. {
  89. FunWrap();
  90. using Fun::swap;
  91. private_type swap(dont_care) const;
  92. };
  93. static Fun &declval_fun();
  94. static FunWrap declval_wrap();
  95. static bool const value =
  96. sizeof(no_type) == sizeof(is_private_type( (declval_wrap().swap(declval_fun()), 0)) );
  97. };
  98. template<typename Fun>
  99. struct has_member_swap : public has_member_swap_impl
  100. <Fun, has_member_function_named_swap<Fun>::value>
  101. {};
  102. } //namespace boost_move_member_swap
  103. namespace boost_move_adl_swap{
  104. template<class P1, class P2, bool = P1::value>
  105. struct and_op_impl
  106. { static const bool value = false; };
  107. template<class P1, class P2>
  108. struct and_op_impl<P1, P2, true>
  109. { static const bool value = P2::value; };
  110. template<class P1, class P2>
  111. struct and_op
  112. : and_op_impl<P1, P2>
  113. {};
  114. //////
  115. template<class P1, class P2, bool = P1::value>
  116. struct and_op_not_impl
  117. { static const bool value = false; };
  118. template<class P1, class P2>
  119. struct and_op_not_impl<P1, P2, true>
  120. { static const bool value = !P2::value; };
  121. template<class P1, class P2>
  122. struct and_op_not
  123. : and_op_not_impl<P1, P2>
  124. {};
  125. template<class T>
  126. 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)
  127. {
  128. //use std::swap if argument dependent lookup fails
  129. //Use using directive ("using namespace xxx;") instead as some older compilers
  130. //don't do ADL with using declarations ("using ns::func;").
  131. using namespace std;
  132. swap(x, y);
  133. }
  134. template<class T>
  135. void swap_proxy(T& x, T& y
  136. , typename boost::move_detail::enable_if< and_op_not_impl<boost::move_detail::has_move_emulation_enabled_impl<T>
  137. , boost_move_member_swap::has_member_swap<T> >
  138. >::type* = 0)
  139. { T t(::boost::move(x)); x = ::boost::move(y); y = ::boost::move(t); }
  140. template<class T>
  141. inline void swap_proxy(T& x, T& y
  142. , typename boost::move_detail::enable_if< and_op_impl< boost::move_detail::has_move_emulation_enabled_impl<T>
  143. , boost_move_member_swap::has_member_swap<T> >
  144. >::type* = 0)
  145. { x.swap(y); }
  146. } //namespace boost_move_adl_swap{
  147. #else
  148. namespace boost_move_adl_swap{
  149. template<class T>
  150. inline void swap_proxy(T& x, T& y)
  151. {
  152. using std::swap;
  153. swap(x, y);
  154. }
  155. } //namespace boost_move_adl_swap{
  156. #endif //#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  157. namespace boost_move_adl_swap{
  158. template<class T, std::size_t N>
  159. void swap_proxy(T (& x)[N], T (& y)[N])
  160. {
  161. for (std::size_t i = 0; i < N; ++i){
  162. ::boost_move_adl_swap::swap_proxy(x[i], y[i]);
  163. }
  164. }
  165. } //namespace boost_move_adl_swap {
  166. #endif //!defined(BOOST_MOVE_DOXYGEN_INVOKED)
  167. namespace boost{
  168. //! Exchanges the values of a and b, using Argument Dependent Lookup (ADL) to select a
  169. //! specialized swap function if available. If no specialized swap function is available,
  170. //! std::swap is used.
  171. //!
  172. //! <b>Exception</b>: If T uses Boost.Move's move emulation and the compiler has
  173. //! no rvalue references then:
  174. //!
  175. //! - If T has a <code>T::swap(T&)</code> member, that member is called.
  176. //! - Otherwise a move-based swap is called, equivalent to:
  177. //! <code>T t(::boost::move(x)); x = ::boost::move(y); y = ::boost::move(t);</code>.
  178. template<class T>
  179. inline void adl_move_swap(T& x, T& y)
  180. {
  181. ::boost_move_adl_swap::swap_proxy(x, y);
  182. }
  183. //! Exchanges elements between range [first1, last1) and another range starting at first2
  184. //! using boost::adl_move_swap.
  185. //!
  186. //! Parameters:
  187. //! first1, last1 - the first range of elements to swap
  188. //! first2 - beginning of the second range of elements to swap
  189. //!
  190. //! Type requirements:
  191. //! - ForwardIt1, ForwardIt2 must meet the requirements of ForwardIterator.
  192. //! - The types of dereferenced ForwardIt1 and ForwardIt2 must meet the
  193. //! requirements of Swappable
  194. //!
  195. //! Return value: Iterator to the element past the last element exchanged in the range
  196. //! beginning with first2.
  197. template<class ForwardIt1, class ForwardIt2>
  198. ForwardIt2 adl_move_swap_ranges(ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2)
  199. {
  200. while (first1 != last1) {
  201. ::boost::adl_move_swap(*first1, *first2);
  202. ++first1;
  203. ++first2;
  204. }
  205. return first2;
  206. }
  207. template<class BidirIt1, class BidirIt2>
  208. BidirIt2 adl_move_swap_ranges_backward(BidirIt1 first1, BidirIt1 last1, BidirIt2 last2)
  209. {
  210. while (first1 != last1) {
  211. ::boost::adl_move_swap(*(--last1), *(--last2));
  212. }
  213. return last2;
  214. }
  215. template<class ForwardIt1, class ForwardIt2>
  216. void adl_move_iter_swap(ForwardIt1 a, ForwardIt2 b)
  217. {
  218. boost::adl_move_swap(*a, *b);
  219. }
  220. } //namespace boost{
  221. #endif //#ifndef BOOST_MOVE_ADL_MOVE_SWAP_HPP