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

source code of boost/boost/move/core.hpp