1 //////////////////////////////////////////////////////////////////////////////
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)
8 // See http://www.boost.org/libs/move for documentation.
10 //////////////////////////////////////////////////////////////////////////////
13 //! This header defines core utilities to ease the development
14 //! of move-aware functions. This header minimizes dependencies
15 //! from other libraries.
17 #ifndef BOOST_MOVE_MOVE_UTILITY_CORE_HPP
18 #define BOOST_MOVE_MOVE_UTILITY_CORE_HPP
20 #ifndef BOOST_CONFIG_HPP
21 # include <boost/config.hpp>
24 #if defined(BOOST_HAS_PRAGMA_ONCE)
28 #include <boost/move/detail/config_begin.hpp>
29 #include <boost/move/core.hpp>
30 #include <boost/move/detail/meta_utils.hpp>
31 #include <boost/static_assert.hpp>
33 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED)
38 struct enable_move_utility_emulation
40 static const bool value = true;
43 //////////////////////////////////////////////////////////////////////////////
47 //////////////////////////////////////////////////////////////////////////////
50 inline typename ::boost::move_detail::enable_if_and
52 , enable_move_utility_emulation<T>
53 , has_move_emulation_disabled<T>
55 move(T& x) BOOST_NOEXCEPT
61 inline typename ::boost::move_detail::enable_if_and
63 , enable_move_utility_emulation<T>
64 , has_move_emulation_enabled<T>
66 move(T& x) BOOST_NOEXCEPT
68 return *BOOST_MOVE_TO_RV_CAST(::boost::rv<T>*, ::boost::move_detail::addressof(x) );
72 inline typename ::boost::move_detail::enable_if_and
74 , enable_move_utility_emulation<T>
75 , has_move_emulation_enabled<T>
77 move(rv<T>& x) BOOST_NOEXCEPT
82 //////////////////////////////////////////////////////////////////////////////
86 //////////////////////////////////////////////////////////////////////////////
89 inline typename ::boost::move_detail::enable_if_and
91 , enable_move_utility_emulation<T>
92 , ::boost::move_detail::is_rv<T>
94 forward(const typename ::boost::move_detail::identity<T>::type &x) BOOST_NOEXCEPT
96 return const_cast<T&>(x);
100 inline typename ::boost::move_detail::enable_if_and
102 , enable_move_utility_emulation<T>
103 , ::boost::move_detail::is_not_rv<T>
105 forward(const typename ::boost::move_detail::identity<T>::type &x) BOOST_NOEXCEPT
110 //////////////////////////////////////////////////////////////////////////////
112 // move_if_not_lvalue_reference()
114 //////////////////////////////////////////////////////////////////////////////
117 inline typename ::boost::move_detail::enable_if_and
119 , enable_move_utility_emulation<T>
120 , ::boost::move_detail::is_rv<T>
122 move_if_not_lvalue_reference(const typename ::boost::move_detail::identity<T>::type &x) BOOST_NOEXCEPT
124 return const_cast<T&>(x);
128 inline typename ::boost::move_detail::enable_if_and
129 < typename ::boost::move_detail::add_lvalue_reference<T>::type
130 , enable_move_utility_emulation<T>
131 , ::boost::move_detail::is_not_rv<T>
132 , ::boost::move_detail::or_
133 < ::boost::move_detail::is_lvalue_reference<T>
134 , has_move_emulation_disabled<T>
137 move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type &x) BOOST_NOEXCEPT
143 inline typename ::boost::move_detail::enable_if_and
145 , enable_move_utility_emulation<T>
146 , ::boost::move_detail::is_not_rv<T>
147 , ::boost::move_detail::and_
148 < ::boost::move_detail::not_< ::boost::move_detail::is_lvalue_reference<T> >
149 , has_move_emulation_enabled<T>
152 move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type &x) BOOST_NOEXCEPT
159 #else //#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED)
161 #if defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE)
167 using ::std::forward;
171 #else //!BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE
175 //! This trait's internal boolean `value` is false in compilers with rvalue references
176 //! and true in compilers without rvalue references.
178 //! A user can specialize this trait for a type T to false to SFINAE out `move` and `forward`
179 //! so that the user can define a different move emulation for that type in namespace boost
180 //! (e.g. another Boost library for its types) and avoid any overload ambiguity.
182 struct enable_move_utility_emulation
184 static const bool value = false;
187 //////////////////////////////////////////////////////////////////////////////
191 //////////////////////////////////////////////////////////////////////////////
193 #if defined(BOOST_MOVE_DOXYGEN_INVOKED)
194 //! This function provides a way to convert a reference into a rvalue reference
195 //! in compilers with rvalue references. For other compilers if `T` is Boost.Move
196 //! enabled type then it converts `T&` into <tt>::boost::rv<T> &</tt> so that
197 //! move emulation is activated, else it returns `T &`.
199 rvalue_reference move(input_reference) noexcept;
201 #elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES)
203 //Old move approach, lvalues could bind to rvalue references
205 inline typename ::boost::move_detail::remove_reference<T>::type && move(T&& t) BOOST_NOEXCEPT
208 #else //BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
211 inline typename ::boost::move_detail::remove_reference<T>::type && move(T&& t) BOOST_NOEXCEPT
212 { return static_cast<typename ::boost::move_detail::remove_reference<T>::type &&>(t); }
214 #endif //BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
216 //////////////////////////////////////////////////////////////////////////////
220 //////////////////////////////////////////////////////////////////////////////
223 #if defined(BOOST_MOVE_DOXYGEN_INVOKED)
224 //! This function provides limited form of forwarding that is usually enough for
225 //! in-place construction and avoids the exponential overloading for
226 //! achieve the limited forwarding in C++03.
228 //! For compilers with rvalue references this function provides perfect forwarding.
231 //! * If input_reference binds to const ::boost::rv<T> & then it output_reference is
234 //! * Else, output_reference is equal to input_reference.
235 template <class T> output_reference forward(input_reference) noexcept;
236 #elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES)
238 //Old move approach, lvalues could bind to rvalue references
241 inline T&& forward(typename ::boost::move_detail::identity<T>::type&& t) BOOST_NOEXCEPT
247 inline T&& forward(typename ::boost::move_detail::remove_reference<T>::type& t) BOOST_NOEXCEPT
248 { return static_cast<T&&>(t); }
251 inline T&& forward(typename ::boost::move_detail::remove_reference<T>::type&& t) BOOST_NOEXCEPT
253 //"boost::forward<T> error: 'T' is a lvalue reference, can't forward as rvalue.";
254 BOOST_STATIC_ASSERT(!boost::move_detail::is_lvalue_reference<T>::value);
255 return static_cast<T&&>(t);
258 #endif //BOOST_MOVE_DOXYGEN_INVOKED
260 //////////////////////////////////////////////////////////////////////////////
262 // move_if_not_lvalue_reference
264 //////////////////////////////////////////////////////////////////////////////
267 #if defined(BOOST_MOVE_DOXYGEN_INVOKED)
268 template <class T> output_reference move_if_not_lvalue_reference(input_reference) noexcept;
269 #elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES)
271 //Old move approach, lvalues could bind to rvalue references
274 inline T&& move_if_not_lvalue_reference(typename ::boost::move_detail::identity<T>::type&& t) BOOST_NOEXCEPT
280 inline T&& move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type& t) BOOST_NOEXCEPT
281 { return static_cast<T&&>(t); }
284 inline T&& move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type&& t) BOOST_NOEXCEPT
286 //"boost::forward<T> error: 'T' is a lvalue reference, can't forward as rvalue.";
287 BOOST_STATIC_ASSERT(!boost::move_detail::is_lvalue_reference<T>::value);
288 return static_cast<T&&>(t);
291 #endif //BOOST_MOVE_DOXYGEN_INVOKED
293 } //namespace boost {
295 #endif //#if defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE)
297 #endif //BOOST_NO_CXX11_RVALUE_REFERENCES
299 #if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
302 namespace move_detail{
304 template <typename T>
305 typename boost::move_detail::add_rvalue_reference<T>::type declval();
307 } //namespace move_detail{
310 #endif //#if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
313 #include <boost/move/detail/config_end.hpp>
315 #endif //#ifndef BOOST_MOVE_MOVE_UTILITY_CORE_HPP