utility_core.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2012-2012.
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. // See http://www.boost.org/libs/move for documentation.
  9. //
  10. //////////////////////////////////////////////////////////////////////////////
  11. //! \file
  12. //! This header defines core utilities to ease the development
  13. //! of move-aware functions. This header minimizes dependencies
  14. //! from other libraries.
  15. #ifndef BOOST_MOVE_MOVE_UTILITY_CORE_HPP
  16. #define BOOST_MOVE_MOVE_UTILITY_CORE_HPP
  17. #ifndef BOOST_CONFIG_HPP
  18. # include <boost/config.hpp>
  19. #endif
  20. #
  21. #if defined(BOOST_HAS_PRAGMA_ONCE)
  22. # pragma once
  23. #endif
  24. #include <boost/move/detail/config_begin.hpp>
  25. #include <boost/move/detail/workaround.hpp> //forceinline
  26. #include <boost/move/core.hpp>
  27. #include <boost/move/detail/meta_utils.hpp>
  28. #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED)
  29. namespace boost {
  30. template<class T>
  31. struct enable_move_utility_emulation
  32. {
  33. static const bool value = true;
  34. };
  35. //////////////////////////////////////////////////////////////////////////////
  36. //
  37. // move()
  38. //
  39. //////////////////////////////////////////////////////////////////////////////
  40. template <class T>
  41. BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
  42. < T &
  43. , enable_move_utility_emulation<T>
  44. , has_move_emulation_disabled<T>
  45. >::type
  46. move(T& x) BOOST_NOEXCEPT
  47. {
  48. return x;
  49. }
  50. template <class T>
  51. BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
  52. < rv<T>&
  53. , enable_move_utility_emulation<T>
  54. , has_move_emulation_enabled<T>
  55. >::type
  56. move(T& x) BOOST_NOEXCEPT
  57. {
  58. return *BOOST_MOVE_TO_RV_CAST(::boost::rv<T>*, ::boost::move_detail::addressof(x) );
  59. }
  60. template <class T>
  61. BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
  62. < rv<T>&
  63. , enable_move_utility_emulation<T>
  64. , has_move_emulation_enabled<T>
  65. >::type
  66. move(rv<T>& x) BOOST_NOEXCEPT
  67. {
  68. return x;
  69. }
  70. //////////////////////////////////////////////////////////////////////////////
  71. //
  72. // forward()
  73. //
  74. //////////////////////////////////////////////////////////////////////////////
  75. template <class T>
  76. BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
  77. < T &
  78. , enable_move_utility_emulation<T>
  79. , ::boost::move_detail::is_rv<T>
  80. >::type
  81. forward(const typename ::boost::move_detail::identity<T>::type &x) BOOST_NOEXCEPT
  82. {
  83. return const_cast<T&>(x);
  84. }
  85. template <class T>
  86. BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
  87. < const T &
  88. , enable_move_utility_emulation<T>
  89. , ::boost::move_detail::is_not_rv<T>
  90. >::type
  91. forward(const typename ::boost::move_detail::identity<T>::type &x) BOOST_NOEXCEPT
  92. {
  93. return x;
  94. }
  95. //////////////////////////////////////////////////////////////////////////////
  96. //
  97. // move_if_not_lvalue_reference()
  98. //
  99. //////////////////////////////////////////////////////////////////////////////
  100. template <class T>
  101. BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
  102. < T &
  103. , enable_move_utility_emulation<T>
  104. , ::boost::move_detail::is_rv<T>
  105. >::type
  106. move_if_not_lvalue_reference(const typename ::boost::move_detail::identity<T>::type &x) BOOST_NOEXCEPT
  107. {
  108. return const_cast<T&>(x);
  109. }
  110. template <class T>
  111. BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
  112. < typename ::boost::move_detail::add_lvalue_reference<T>::type
  113. , enable_move_utility_emulation<T>
  114. , ::boost::move_detail::is_not_rv<T>
  115. , ::boost::move_detail::or_
  116. < ::boost::move_detail::is_lvalue_reference<T>
  117. , has_move_emulation_disabled<T>
  118. >
  119. >::type
  120. move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type &x) BOOST_NOEXCEPT
  121. {
  122. return x;
  123. }
  124. template <class T>
  125. BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
  126. < rv<T>&
  127. , enable_move_utility_emulation<T>
  128. , ::boost::move_detail::is_not_rv<T>
  129. , ::boost::move_detail::and_
  130. < ::boost::move_detail::not_< ::boost::move_detail::is_lvalue_reference<T> >
  131. , has_move_emulation_enabled<T>
  132. >
  133. >::type
  134. move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type &x) BOOST_NOEXCEPT
  135. {
  136. return move(x);
  137. }
  138. } //namespace boost
  139. #else //#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED)
  140. #if defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE)
  141. #include <utility>
  142. namespace boost{
  143. using ::std::move;
  144. using ::std::forward;
  145. } //namespace boost
  146. #else //!BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE
  147. namespace boost {
  148. //! This trait's internal boolean `value` is false in compilers with rvalue references
  149. //! and true in compilers without rvalue references.
  150. //!
  151. //! A user can specialize this trait for a type T to false to SFINAE out `move` and `forward`
  152. //! so that the user can define a different move emulation for that type in namespace boost
  153. //! (e.g. another Boost library for its types) and avoid any overload ambiguity.
  154. template<class T>
  155. struct enable_move_utility_emulation
  156. {
  157. static const bool value = false;
  158. };
  159. //////////////////////////////////////////////////////////////////////////////
  160. //
  161. // move
  162. //
  163. //////////////////////////////////////////////////////////////////////////////
  164. #if defined(BOOST_MOVE_DOXYGEN_INVOKED)
  165. //! This function provides a way to convert a reference into a rvalue reference
  166. //! in compilers with rvalue references. For other compilers if `T` is Boost.Move
  167. //! enabled type then it converts `T&` into <tt>::boost::rv<T> &</tt> so that
  168. //! move emulation is activated, else it returns `T &`.
  169. template <class T>
  170. rvalue_reference move(input_reference) noexcept;
  171. #elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES)
  172. //Old move approach, lvalues could bind to rvalue references
  173. template <class T>
  174. BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::remove_reference<T>::type && move(T&& t) BOOST_NOEXCEPT
  175. { return t; }
  176. #else //BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
  177. template <class T>
  178. BOOST_MOVE_INTRINSIC_CAST
  179. typename ::boost::move_detail::remove_reference<T>::type && move(T&& t) BOOST_NOEXCEPT
  180. { return static_cast<typename ::boost::move_detail::remove_reference<T>::type &&>(t); }
  181. #endif //BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
  182. //////////////////////////////////////////////////////////////////////////////
  183. //
  184. // forward
  185. //
  186. //////////////////////////////////////////////////////////////////////////////
  187. #if defined(BOOST_MOVE_DOXYGEN_INVOKED)
  188. //! This function provides limited form of forwarding that is usually enough for
  189. //! in-place construction and avoids the exponential overloading for
  190. //! achieve the limited forwarding in C++03.
  191. //!
  192. //! For compilers with rvalue references this function provides perfect forwarding.
  193. //!
  194. //! Otherwise:
  195. //! * If input_reference binds to const ::boost::rv<T> & then it output_reference is
  196. //! ::boost::rv<T> &
  197. //!
  198. //! * Else, output_reference is equal to input_reference.
  199. template <class T> output_reference forward(input_reference) noexcept;
  200. #elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES)
  201. //Old move approach, lvalues could bind to rvalue references
  202. template <class T>
  203. BOOST_MOVE_FORCEINLINE T&& forward(typename ::boost::move_detail::identity<T>::type&& t) BOOST_NOEXCEPT
  204. { return t; }
  205. #else //Old move
  206. template <class T>
  207. BOOST_MOVE_INTRINSIC_CAST
  208. T&& forward(typename ::boost::move_detail::remove_reference<T>::type& t) BOOST_NOEXCEPT
  209. { return static_cast<T&&>(t); }
  210. template <class T>
  211. BOOST_MOVE_INTRINSIC_CAST
  212. T&& forward(typename ::boost::move_detail::remove_reference<T>::type&& t) BOOST_NOEXCEPT
  213. {
  214. //"boost::forward<T> error: 'T' is a lvalue reference, can't forward as rvalue.";
  215. BOOST_MOVE_STATIC_ASSERT(!boost::move_detail::is_lvalue_reference<T>::value);
  216. return static_cast<T&&>(t);
  217. }
  218. #endif //BOOST_MOVE_DOXYGEN_INVOKED
  219. } //namespace boost {
  220. #endif //BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE
  221. //////////////////////////////////////////////////////////////////////////////
  222. //
  223. // move_if_not_lvalue_reference
  224. //
  225. //////////////////////////////////////////////////////////////////////////////
  226. namespace boost {
  227. #if defined(BOOST_MOVE_DOXYGEN_INVOKED)
  228. //! <b>Effects</b>: Calls `boost::move` if `input_reference` is not a lvalue reference.
  229. //! Otherwise returns the reference
  230. template <class T> output_reference move_if_not_lvalue_reference(input_reference) noexcept;
  231. #elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES)
  232. //Old move approach, lvalues could bind to rvalue references
  233. template <class T>
  234. BOOST_MOVE_FORCEINLINE T&& move_if_not_lvalue_reference(typename ::boost::move_detail::identity<T>::type&& t) BOOST_NOEXCEPT
  235. { return t; }
  236. #else //Old move
  237. template <class T>
  238. BOOST_MOVE_FORCEINLINE T&& move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type& t) BOOST_NOEXCEPT
  239. { return static_cast<T&&>(t); }
  240. template <class T>
  241. BOOST_MOVE_FORCEINLINE T&& move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type&& t) BOOST_NOEXCEPT
  242. {
  243. //"boost::forward<T> error: 'T' is a lvalue reference, can't forward as rvalue.";
  244. BOOST_MOVE_STATIC_ASSERT(!boost::move_detail::is_lvalue_reference<T>::value);
  245. return static_cast<T&&>(t);
  246. }
  247. #endif //BOOST_MOVE_DOXYGEN_INVOKED
  248. } //namespace boost {
  249. #endif //BOOST_NO_CXX11_RVALUE_REFERENCES
  250. #if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
  251. namespace boost{
  252. namespace move_detail{
  253. template <typename T>
  254. typename boost::move_detail::add_rvalue_reference<T>::type declval();
  255. } //namespace move_detail{
  256. } //namespace boost{
  257. #endif //#if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
  258. #include <boost/move/detail/config_end.hpp>
  259. #endif //#ifndef BOOST_MOVE_MOVE_UTILITY_CORE_HPP