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