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 #if defined(BOOST_MOVE_ADDRESS_SANITIZER_ON)
61 #define BOOST_MOVE_TO_RV_CAST(RV_TYPE, ARG) reinterpret_cast<RV_TYPE>(ARG)
62 #else
63 #define BOOST_MOVE_TO_RV_CAST(RV_TYPE, ARG) static_cast<RV_TYPE>(ARG)
64 #endif
65
66 //Move emulation rv breaks standard aliasing rules so add workarounds for some compilers
67 #define BOOST_MOVE_ATTRIBUTE_MAY_ALIAS BOOST_MAY_ALIAS
68
69 namespace boost {
70
71 //////////////////////////////////////////////////////////////////////////////
72 //
73 // struct rv
74 //
75 //////////////////////////////////////////////////////////////////////////////
76 template <class T>
77 class 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 } BOOST_MOVE_ATTRIBUTE_MAY_ALIAS;
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