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 implements macros to define movable classes and |
14 | //! move-aware functions |
15 | |
16 | #ifndef BOOST_MOVE_CORE_HPP |
17 | #define BOOST_MOVE_CORE_HPP |
18 | |
19 | #ifndef BOOST_CONFIG_HPP |
20 | # include <boost/config.hpp> |
21 | #endif |
22 | # |
23 | #if defined(BOOST_HAS_PRAGMA_ONCE) |
24 | # pragma once |
25 | #endif |
26 | |
27 | #include <boost/move/detail/config_begin.hpp> |
28 | #include <boost/move/detail/workaround.hpp> |
29 | |
30 | // @cond |
31 | |
32 | //boost_move_no_copy_constructor_or_assign typedef |
33 | //used to detect noncopyable types for other Boost libraries. |
34 | #if defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES) |
35 | #define BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE) \ |
36 | private:\ |
37 | TYPE(TYPE &);\ |
38 | TYPE& operator=(TYPE &);\ |
39 | public:\ |
40 | typedef int boost_move_no_copy_constructor_or_assign; \ |
41 | private:\ |
42 | // |
43 | #else |
44 | #define BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE) \ |
45 | public:\ |
46 | TYPE(TYPE const &) = delete;\ |
47 | TYPE& operator=(TYPE const &) = delete;\ |
48 | public:\ |
49 | typedef int boost_move_no_copy_constructor_or_assign; \ |
50 | private:\ |
51 | // |
52 | #endif //BOOST_NO_CXX11_DELETED_FUNCTIONS |
53 | |
54 | // @endcond |
55 | |
56 | #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED) |
57 | |
58 | #include <boost/move/detail/type_traits.hpp> |
59 | |
60 | #define BOOST_MOVE_TO_RV_CAST(RV_TYPE, ARG) reinterpret_cast<RV_TYPE>(ARG) |
61 | |
62 | //Move emulation rv breaks standard aliasing rules so add workarounds for some compilers |
63 | #if defined(BOOST_GCC) && (BOOST_GCC >= 40400) && (BOOST_GCC < 40500) |
64 | #define BOOST_RV_ATTRIBUTE_MAY_ALIAS BOOST_MAY_ALIAS |
65 | #else |
66 | #define BOOST_RV_ATTRIBUTE_MAY_ALIAS |
67 | #endif |
68 | |
69 | namespace boost { |
70 | |
71 | ////////////////////////////////////////////////////////////////////////////// |
72 | // |
73 | // struct rv |
74 | // |
75 | ////////////////////////////////////////////////////////////////////////////// |
76 | template <class T> |
77 | class BOOST_RV_ATTRIBUTE_MAY_ALIAS rv |
78 | : public ::boost::move_detail::if_c |
79 | < ::boost::move_detail::is_class<T>::value |
80 | , T |
81 | , ::boost::move_detail::nat |
82 | >::type |
83 | { |
84 | rv(); |
85 | ~rv() throw(); |
86 | rv(rv const&); |
87 | void operator=(rv const&); |
88 | }; |
89 | |
90 | |
91 | ////////////////////////////////////////////////////////////////////////////// |
92 | // |
93 | // is_rv |
94 | // |
95 | ////////////////////////////////////////////////////////////////////////////// |
96 | |
97 | namespace move_detail { |
98 | |
99 | template <class T> |
100 | struct is_rv |
101 | //Derive from integral constant because some Boost code assummes it has |
102 | //a "type" internal typedef |
103 | : integral_constant<bool, ::boost::move_detail::is_rv_impl<T>::value > |
104 | {}; |
105 | |
106 | template <class T> |
107 | struct is_not_rv |
108 | { |
109 | static const bool value = !is_rv<T>::value; |
110 | }; |
111 | |
112 | } //namespace move_detail { |
113 | |
114 | ////////////////////////////////////////////////////////////////////////////// |
115 | // |
116 | // has_move_emulation_enabled |
117 | // |
118 | ////////////////////////////////////////////////////////////////////////////// |
119 | template<class T> |
120 | struct has_move_emulation_enabled |
121 | : ::boost::move_detail::has_move_emulation_enabled_impl<T> |
122 | {}; |
123 | |
124 | template<class T> |
125 | struct has_move_emulation_disabled |
126 | { |
127 | static const bool value = !::boost::move_detail::has_move_emulation_enabled_impl<T>::value; |
128 | }; |
129 | |
130 | } //namespace boost { |
131 | |
132 | #define BOOST_RV_REF(TYPE)\ |
133 | ::boost::rv< TYPE >& \ |
134 | // |
135 | |
136 | #define BOOST_RV_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\ |
137 | ::boost::rv< TYPE<ARG1, ARG2> >& \ |
138 | // |
139 | |
140 | #define BOOST_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ |
141 | ::boost::rv< TYPE<ARG1, ARG2, ARG3> >& \ |
142 | // |
143 | |
144 | #define BOOST_RV_REF_BEG\ |
145 | ::boost::rv< \ |
146 | // |
147 | |
148 | #define BOOST_RV_REF_END\ |
149 | >& \ |
150 | // |
151 | |
152 | #define BOOST_RV_REF_BEG_IF_CXX11 \ |
153 | \ |
154 | // |
155 | |
156 | #define BOOST_RV_REF_END_IF_CXX11 \ |
157 | \ |
158 | // |
159 | |
160 | #define BOOST_FWD_REF(TYPE)\ |
161 | const TYPE & \ |
162 | // |
163 | |
164 | #define BOOST_COPY_ASSIGN_REF(TYPE)\ |
165 | const ::boost::rv< TYPE >& \ |
166 | // |
167 | |
168 | #define BOOST_COPY_ASSIGN_REF_BEG \ |
169 | const ::boost::rv< \ |
170 | // |
171 | |
172 | #define BOOST_COPY_ASSIGN_REF_END \ |
173 | >& \ |
174 | // |
175 | |
176 | #define BOOST_COPY_ASSIGN_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\ |
177 | const ::boost::rv< TYPE<ARG1, ARG2> >& \ |
178 | // |
179 | |
180 | #define BOOST_COPY_ASSIGN_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ |
181 | const ::boost::rv< TYPE<ARG1, ARG2, ARG3> >& \ |
182 | // |
183 | |
184 | #define BOOST_CATCH_CONST_RLVALUE(TYPE)\ |
185 | const ::boost::rv< TYPE >& \ |
186 | // |
187 | |
188 | namespace boost { |
189 | namespace move_detail { |
190 | |
191 | template <class Ret, class T> |
192 | BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c |
193 | < ::boost::move_detail::is_lvalue_reference<Ret>::value || |
194 | !::boost::has_move_emulation_enabled<T>::value |
195 | , T&>::type |
196 | move_return(T& x) BOOST_NOEXCEPT |
197 | { |
198 | return x; |
199 | } |
200 | |
201 | template <class Ret, class T> |
202 | BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c |
203 | < !::boost::move_detail::is_lvalue_reference<Ret>::value && |
204 | ::boost::has_move_emulation_enabled<T>::value |
205 | , ::boost::rv<T>&>::type |
206 | move_return(T& x) BOOST_NOEXCEPT |
207 | { |
208 | return *BOOST_MOVE_TO_RV_CAST(::boost::rv<T>*, ::boost::move_detail::addressof(x)); |
209 | } |
210 | |
211 | template <class Ret, class T> |
212 | BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c |
213 | < !::boost::move_detail::is_lvalue_reference<Ret>::value && |
214 | ::boost::has_move_emulation_enabled<T>::value |
215 | , ::boost::rv<T>&>::type |
216 | move_return(::boost::rv<T>& x) BOOST_NOEXCEPT |
217 | { |
218 | return x; |
219 | } |
220 | |
221 | } //namespace move_detail { |
222 | } //namespace boost { |
223 | |
224 | #define BOOST_MOVE_RET(RET_TYPE, REF)\ |
225 | boost::move_detail::move_return< RET_TYPE >(REF) |
226 | // |
227 | |
228 | #define BOOST_MOVE_BASE(BASE_TYPE, ARG) \ |
229 | ::boost::move((BASE_TYPE&)(ARG)) |
230 | // |
231 | |
232 | ////////////////////////////////////////////////////////////////////////////// |
233 | // |
234 | // BOOST_MOVABLE_BUT_NOT_COPYABLE |
235 | // |
236 | ////////////////////////////////////////////////////////////////////////////// |
237 | #define BOOST_MOVABLE_BUT_NOT_COPYABLE(TYPE)\ |
238 | BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE)\ |
239 | public:\ |
240 | BOOST_MOVE_FORCEINLINE operator ::boost::rv<TYPE>&() \ |
241 | { return *BOOST_MOVE_TO_RV_CAST(::boost::rv<TYPE>*, this); }\ |
242 | BOOST_MOVE_FORCEINLINE operator const ::boost::rv<TYPE>&() const \ |
243 | { return *BOOST_MOVE_TO_RV_CAST(const ::boost::rv<TYPE>*, this); }\ |
244 | private:\ |
245 | // |
246 | |
247 | ////////////////////////////////////////////////////////////////////////////// |
248 | // |
249 | // BOOST_COPYABLE_AND_MOVABLE |
250 | // |
251 | ////////////////////////////////////////////////////////////////////////////// |
252 | |
253 | #define BOOST_COPYABLE_AND_MOVABLE(TYPE)\ |
254 | public:\ |
255 | BOOST_MOVE_FORCEINLINE TYPE& operator=(TYPE &t)\ |
256 | { this->operator=(const_cast<const TYPE&>(t)); return *this;}\ |
257 | public:\ |
258 | BOOST_MOVE_FORCEINLINE operator ::boost::rv<TYPE>&() \ |
259 | { return *BOOST_MOVE_TO_RV_CAST(::boost::rv<TYPE>*, this); }\ |
260 | BOOST_MOVE_FORCEINLINE operator const ::boost::rv<TYPE>&() const \ |
261 | { return *BOOST_MOVE_TO_RV_CAST(const ::boost::rv<TYPE>*, this); }\ |
262 | private:\ |
263 | // |
264 | |
265 | #define BOOST_COPYABLE_AND_MOVABLE_ALT(TYPE)\ |
266 | public:\ |
267 | BOOST_MOVE_FORCEINLINE operator ::boost::rv<TYPE>&() \ |
268 | { return *BOOST_MOVE_TO_RV_CAST(::boost::rv<TYPE>*, this); }\ |
269 | BOOST_MOVE_FORCEINLINE operator const ::boost::rv<TYPE>&() const \ |
270 | { return *BOOST_MOVE_TO_RV_CAST(const ::boost::rv<TYPE>*, this); }\ |
271 | private:\ |
272 | // |
273 | |
274 | namespace boost{ |
275 | namespace move_detail{ |
276 | |
277 | template< class T> |
278 | struct forward_type |
279 | { typedef const T &type; }; |
280 | |
281 | template< class T> |
282 | struct forward_type< boost::rv<T> > |
283 | { typedef T type; }; |
284 | |
285 | }} |
286 | |
287 | #else //BOOST_NO_CXX11_RVALUE_REFERENCES |
288 | |
289 | //! This macro marks a type as movable but not copyable, disabling copy construction |
290 | //! and assignment. The user will need to write a move constructor/assignment as explained |
291 | //! in the documentation to fully write a movable but not copyable class. |
292 | #define BOOST_MOVABLE_BUT_NOT_COPYABLE(TYPE)\ |
293 | BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE)\ |
294 | public:\ |
295 | typedef int boost_move_emulation_t;\ |
296 | private:\ |
297 | // |
298 | |
299 | //! This macro marks a type as copyable and movable. |
300 | //! The user will need to write a move constructor/assignment and a copy assignment |
301 | //! as explained in the documentation to fully write a copyable and movable class. |
302 | #define BOOST_COPYABLE_AND_MOVABLE(TYPE)\ |
303 | // |
304 | |
305 | #if !defined(BOOST_MOVE_DOXYGEN_INVOKED) |
306 | #define BOOST_COPYABLE_AND_MOVABLE_ALT(TYPE)\ |
307 | // |
308 | #endif //#if !defined(BOOST_MOVE_DOXYGEN_INVOKED) |
309 | |
310 | namespace boost { |
311 | |
312 | //!This trait yields to a compile-time true boolean if T was marked as |
313 | //!BOOST_MOVABLE_BUT_NOT_COPYABLE or BOOST_COPYABLE_AND_MOVABLE and |
314 | //!rvalue references are not available on the platform. False otherwise. |
315 | template<class T> |
316 | struct has_move_emulation_enabled |
317 | { |
318 | static const bool value = false; |
319 | }; |
320 | |
321 | template<class T> |
322 | struct has_move_emulation_disabled |
323 | { |
324 | static const bool value = true; |
325 | }; |
326 | |
327 | } //namespace boost{ |
328 | |
329 | //!This macro is used to achieve portable syntax in move |
330 | //!constructors and assignments for classes marked as |
331 | //!BOOST_COPYABLE_AND_MOVABLE or BOOST_MOVABLE_BUT_NOT_COPYABLE |
332 | #define BOOST_RV_REF(TYPE)\ |
333 | TYPE && \ |
334 | // |
335 | |
336 | //!This macro is used to achieve portable syntax in move |
337 | //!constructors and assignments for template classes marked as |
338 | //!BOOST_COPYABLE_AND_MOVABLE or BOOST_MOVABLE_BUT_NOT_COPYABLE. |
339 | //!As macros have problems with comma-separated template arguments, |
340 | //!the template argument must be preceded with BOOST_RV_REF_BEG |
341 | //!and ended with BOOST_RV_REF_END |
342 | #define BOOST_RV_REF_BEG\ |
343 | \ |
344 | // |
345 | |
346 | //!This macro is used to achieve portable syntax in move |
347 | //!constructors and assignments for template classes marked as |
348 | //!BOOST_COPYABLE_AND_MOVABLE or BOOST_MOVABLE_BUT_NOT_COPYABLE. |
349 | //!As macros have problems with comma-separated template arguments, |
350 | //!the template argument must be preceded with BOOST_RV_REF_BEG |
351 | //!and ended with BOOST_RV_REF_END |
352 | #define BOOST_RV_REF_END\ |
353 | && \ |
354 | // |
355 | |
356 | //!This macro expands to BOOST_RV_REF_BEG if BOOST_NO_CXX11_RVALUE_REFERENCES |
357 | //!is not defined, empty otherwise |
358 | #define BOOST_RV_REF_BEG_IF_CXX11 \ |
359 | BOOST_RV_REF_BEG \ |
360 | // |
361 | |
362 | //!This macro expands to BOOST_RV_REF_END if BOOST_NO_CXX11_RVALUE_REFERENCES |
363 | //!is not defined, empty otherwise |
364 | #define BOOST_RV_REF_END_IF_CXX11 \ |
365 | BOOST_RV_REF_END \ |
366 | // |
367 | |
368 | //!This macro is used to achieve portable syntax in copy |
369 | //!assignment for classes marked as BOOST_COPYABLE_AND_MOVABLE. |
370 | #define BOOST_COPY_ASSIGN_REF(TYPE)\ |
371 | const TYPE & \ |
372 | // |
373 | |
374 | //! This macro is used to implement portable perfect forwarding |
375 | //! as explained in the documentation. |
376 | #define BOOST_FWD_REF(TYPE)\ |
377 | TYPE && \ |
378 | // |
379 | |
380 | #if !defined(BOOST_MOVE_DOXYGEN_INVOKED) |
381 | |
382 | #define BOOST_RV_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\ |
383 | TYPE<ARG1, ARG2> && \ |
384 | // |
385 | |
386 | #define BOOST_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ |
387 | TYPE<ARG1, ARG2, ARG3> && \ |
388 | // |
389 | |
390 | #define BOOST_COPY_ASSIGN_REF_BEG \ |
391 | const \ |
392 | // |
393 | |
394 | #define BOOST_COPY_ASSIGN_REF_END \ |
395 | & \ |
396 | // |
397 | |
398 | #define BOOST_COPY_ASSIGN_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\ |
399 | const TYPE<ARG1, ARG2> & \ |
400 | // |
401 | |
402 | #define BOOST_COPY_ASSIGN_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ |
403 | const TYPE<ARG1, ARG2, ARG3>& \ |
404 | // |
405 | |
406 | #define BOOST_CATCH_CONST_RLVALUE(TYPE)\ |
407 | const TYPE & \ |
408 | // |
409 | |
410 | #endif //#if !defined(BOOST_MOVE_DOXYGEN_INVOKED) |
411 | |
412 | #if !defined(BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG) || defined(BOOST_MOVE_DOXYGEN_INVOKED) |
413 | |
414 | //!This macro is used to achieve portable move return semantics. |
415 | //!The C++11 Standard allows implicit move returns when the object to be returned |
416 | //!is designated by a lvalue and: |
417 | //! - The criteria for elision of a copy operation are met OR |
418 | //! - The criteria would be met save for the fact that the source object is a function parameter |
419 | //! |
420 | //!For C++11 conforming compilers this macros only yields to REF: |
421 | //! <code>return BOOST_MOVE_RET(RET_TYPE, REF);</code> -> <code>return REF;</code> |
422 | //! |
423 | //!For compilers without rvalue references |
424 | //!this macro does an explicit move if the move emulation is activated |
425 | //!and the return type (RET_TYPE) is not a reference. |
426 | //! |
427 | //!For non-conforming compilers with rvalue references like Visual 2010 & 2012, |
428 | //!an explicit move is performed if RET_TYPE is not a reference. |
429 | //! |
430 | //! <b>Caution</b>: When using this macro in non-conforming or C++03 |
431 | //!compilers, a move will be performed even if the C++11 standard does not allow it |
432 | //!(e.g. returning a static variable). The user is responsible for using this macro |
433 | //!only to return local objects that met C++11 criteria. |
434 | #define BOOST_MOVE_RET(RET_TYPE, REF)\ |
435 | REF |
436 | // |
437 | |
438 | #else //!defined(BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG) || defined(BOOST_MOVE_DOXYGEN_INVOKED) |
439 | |
440 | #include <boost/move/detail/meta_utils.hpp> |
441 | |
442 | namespace boost { |
443 | namespace move_detail { |
444 | |
445 | template <class Ret, class T> |
446 | BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c |
447 | < ::boost::move_detail::is_lvalue_reference<Ret>::value |
448 | , T&>::type |
449 | move_return(T& x) BOOST_NOEXCEPT |
450 | { |
451 | return x; |
452 | } |
453 | |
454 | template <class Ret, class T> |
455 | BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c |
456 | < !::boost::move_detail::is_lvalue_reference<Ret>::value |
457 | , Ret && >::type |
458 | move_return(T&& t) BOOST_NOEXCEPT |
459 | { |
460 | return static_cast< Ret&& >(t); |
461 | } |
462 | |
463 | } //namespace move_detail { |
464 | } //namespace boost { |
465 | |
466 | #define BOOST_MOVE_RET(RET_TYPE, REF)\ |
467 | boost::move_detail::move_return< RET_TYPE >(REF) |
468 | // |
469 | |
470 | #endif //!defined(BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG) || defined(BOOST_MOVE_DOXYGEN_INVOKED) |
471 | |
472 | //!This macro is used to achieve portable optimal move constructors. |
473 | //! |
474 | //!When implementing the move constructor, in C++03 compilers the moved-from argument must be |
475 | //!cast to the base type before calling `::boost::move()` due to rvalue reference limitations. |
476 | //! |
477 | //!In C++11 compilers the cast from a rvalue reference of a derived type to a rvalue reference of |
478 | //!a base type is implicit. |
479 | #define BOOST_MOVE_BASE(BASE_TYPE, ARG) \ |
480 | ::boost::move((BASE_TYPE&)(ARG)) |
481 | // |
482 | |
483 | namespace boost { |
484 | namespace move_detail { |
485 | |
486 | template< class T> struct forward_type { typedef T type; }; |
487 | |
488 | }} |
489 | |
490 | #endif //BOOST_NO_CXX11_RVALUE_REFERENCES |
491 | |
492 | #include <boost/move/detail/config_end.hpp> |
493 | |
494 | #endif //#ifndef BOOST_MOVE_CORE_HPP |
495 | |