utility_core.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  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. #include <boost/static_assert.hpp>
  29. #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED)
  30. namespace boost {
  31. template<class T>
  32. struct enable_move_utility_emulation
  33. {
  34. static const bool value = true;
  35. };
  36. //////////////////////////////////////////////////////////////////////////////
  37. //
  38. // move()
  39. //
  40. //////////////////////////////////////////////////////////////////////////////
  41. template <class T>
  42. BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
  43. < T &
  44. , enable_move_utility_emulation<T>
  45. , has_move_emulation_disabled<T>
  46. >::type
  47. move(T& x) BOOST_NOEXCEPT
  48. {
  49. return x;
  50. }
  51. template <class T>
  52. BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
  53. < rv<T>&
  54. , enable_move_utility_emulation<T>
  55. , has_move_emulation_enabled<T>
  56. >::type
  57. move(T& x) BOOST_NOEXCEPT
  58. {
  59. return *BOOST_MOVE_TO_RV_CAST(::boost::rv<T>*, ::boost::move_detail::addressof(x) );
  60. }
  61. template <class T>
  62. BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
  63. < rv<T>&
  64. , enable_move_utility_emulation<T>
  65. , has_move_emulation_enabled<T>
  66. >::type
  67. move(rv<T>& x) BOOST_NOEXCEPT
  68. {
  69. return x;
  70. }
  71. //////////////////////////////////////////////////////////////////////////////
  72. //
  73. // forward()
  74. //
  75. //////////////////////////////////////////////////////////////////////////////
  76. template <class T>
  77. BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
  78. < T &
  79. , enable_move_utility_emulation<T>
  80. , ::boost::move_detail::is_rv<T>
  81. >::type
  82. forward(const typename ::boost::move_detail::identity<T>::type &x) BOOST_NOEXCEPT
  83. {
  84. return const_cast<T&>(x);
  85. }
  86. template <class T>
  87. BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
  88. < const T &
  89. , enable_move_utility_emulation<T>
  90. , ::boost::move_detail::is_not_rv<T>
  91. >::type
  92. forward(const typename ::boost::move_detail::identity<T>::type &x) BOOST_NOEXCEPT
  93. {
  94. return x;
  95. }
  96. //////////////////////////////////////////////////////////////////////////////
  97. //
  98. // move_if_not_lvalue_reference()
  99. //
  100. //////////////////////////////////////////////////////////////////////////////
  101. template <class T>
  102. BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
  103. < T &
  104. , enable_move_utility_emulation<T>
  105. , ::boost::move_detail::is_rv<T>
  106. >::type
  107. move_if_not_lvalue_reference(const typename ::boost::move_detail::identity<T>::type &x) BOOST_NOEXCEPT
  108. {
  109. return const_cast<T&>(x);
  110. }
  111. template <class T>
  112. BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
  113. < typename ::boost::move_detail::add_lvalue_reference<T>::type
  114. , enable_move_utility_emulation<T>
  115. , ::boost::move_detail::is_not_rv<T>
  116. , ::boost::move_detail::or_
  117. < ::boost::move_detail::is_lvalue_reference<T>
  118. , has_move_emulation_disabled<T>
  119. >
  120. >::type
  121. move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type &x) BOOST_NOEXCEPT
  122. {
  123. return x;
  124. }
  125. template <class T>
  126. BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_and
  127. < rv<T>&
  128. , enable_move_utility_emulation<T>
  129. , ::boost::move_detail::is_not_rv<T>
  130. , ::boost::move_detail::and_
  131. < ::boost::move_detail::not_< ::boost::move_detail::is_lvalue_reference<T> >
  132. , has_move_emulation_enabled<T>
  133. >
  134. >::type
  135. move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type &x) BOOST_NOEXCEPT
  136. {
  137. return move(x);
  138. }
  139. } //namespace boost
  140. #else //#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED)
  141. #if defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE)
  142. #include <utility>
  143. namespace boost{
  144. using ::std::move;
  145. using ::std::forward;
  146. } //namespace boost
  147. #else //!BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE
  148. namespace boost {
  149. //! This trait's internal boolean `value` is false in compilers with rvalue references
  150. //! and true in compilers without rvalue references.
  151. //!
  152. //! A user can specialize this trait for a type T to false to SFINAE out `move` and `forward`
  153. //! so that the user can define a different move emulation for that type in namespace boost
  154. //! (e.g. another Boost library for its types) and avoid any overload ambiguity.
  155. template<class T>
  156. struct enable_move_utility_emulation
  157. {
  158. static const bool value = false;
  159. };
  160. //////////////////////////////////////////////////////////////////////////////
  161. //
  162. // move
  163. //
  164. //////////////////////////////////////////////////////////////////////////////
  165. #if defined(BOOST_MOVE_DOXYGEN_INVOKED)
  166. //! This function provides a way to convert a reference into a rvalue reference
  167. //! in compilers with rvalue references. For other compilers if `T` is Boost.Move
  168. //! enabled type then it converts `T&` into <tt>::boost::rv<T> &</tt> so that
  169. //! move emulation is activated, else it returns `T &`.
  170. template <class T>
  171. rvalue_reference move(input_reference) noexcept;
  172. #elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES)
  173. //Old move approach, lvalues could bind to rvalue references
  174. template <class T>
  175. BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::remove_reference<T>::type && move(T&& t) BOOST_NOEXCEPT
  176. { return t; }
  177. #else //BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
  178. template <class T>
  179. BOOST_MOVE_FORCEINLINE 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_FORCEINLINE T&& forward(typename ::boost::move_detail::remove_reference<T>::type& t) BOOST_NOEXCEPT
  208. { return static_cast<T&&>(t); }
  209. template <class T>
  210. BOOST_MOVE_FORCEINLINE T&& forward(typename ::boost::move_detail::remove_reference<T>::type&& t) BOOST_NOEXCEPT
  211. {
  212. //"boost::forward<T> error: 'T' is a lvalue reference, can't forward as rvalue.";
  213. BOOST_STATIC_ASSERT(!boost::move_detail::is_lvalue_reference<T>::value);
  214. return static_cast<T&&>(t);
  215. }
  216. #endif //BOOST_MOVE_DOXYGEN_INVOKED
  217. //////////////////////////////////////////////////////////////////////////////
  218. //
  219. // move_if_not_lvalue_reference
  220. //
  221. //////////////////////////////////////////////////////////////////////////////
  222. #if defined(BOOST_MOVE_DOXYGEN_INVOKED)
  223. //! <b>Effects</b>: Calls `boost::move` if `input_reference` is not a lvalue reference.
  224. //! Otherwise returns the reference
  225. template <class T> output_reference move_if_not_lvalue_reference(input_reference) noexcept;
  226. #elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES)
  227. //Old move approach, lvalues could bind to rvalue references
  228. template <class T>
  229. BOOST_MOVE_FORCEINLINE T&& move_if_not_lvalue_reference(typename ::boost::move_detail::identity<T>::type&& t) BOOST_NOEXCEPT
  230. { return t; }
  231. #else //Old move
  232. template <class T>
  233. BOOST_MOVE_FORCEINLINE T&& move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type& t) BOOST_NOEXCEPT
  234. { return static_cast<T&&>(t); }
  235. template <class T>
  236. BOOST_MOVE_FORCEINLINE T&& move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type&& t) BOOST_NOEXCEPT
  237. {
  238. //"boost::forward<T> error: 'T' is a lvalue reference, can't forward as rvalue.";
  239. BOOST_STATIC_ASSERT(!boost::move_detail::is_lvalue_reference<T>::value);
  240. return static_cast<T&&>(t);
  241. }
  242. #endif //BOOST_MOVE_DOXYGEN_INVOKED
  243. } //namespace boost {
  244. #endif //#if defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE)
  245. #endif //BOOST_NO_CXX11_RVALUE_REFERENCES
  246. #if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
  247. namespace boost{
  248. namespace move_detail{
  249. template <typename T>
  250. typename boost::move_detail::add_rvalue_reference<T>::type declval();
  251. } //namespace move_detail{
  252. } //namespace boost{
  253. #endif //#if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
  254. #include <boost/move/detail/config_end.hpp>
  255. #endif //#ifndef BOOST_MOVE_MOVE_UTILITY_CORE_HPP