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