1 //////////////////////////////////////////////////////////////////////////////
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)
8 // See http://www.boost.org/libs/move for documentation.
10 //////////////////////////////////////////////////////////////////////////////
13 //! This header implements macros to define movable classes and
14 //! move-aware functions
16 #ifndef BOOST_MOVE_CORE_HPP
17 #define BOOST_MOVE_CORE_HPP
19 #ifndef BOOST_CONFIG_HPP
20 # include <boost/config.hpp>
23 #if defined(BOOST_HAS_PRAGMA_ONCE)
27 #include <boost/move/detail/config_begin.hpp>
28 #include <boost/move/detail/workaround.hpp>
30 //boost_move_no_copy_constructor_or_assign typedef
31 //used to detect noncopyable types for other Boost libraries.
32 #if defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
33 #define BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE) \
36 TYPE& operator=(TYPE &);\
38 typedef int boost_move_no_copy_constructor_or_assign; \
42 #define BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE) \
44 TYPE(TYPE const &) = delete;\
45 TYPE& operator=(TYPE const &) = delete;\
47 typedef int boost_move_no_copy_constructor_or_assign; \
50 #endif //BOOST_NO_CXX11_DELETED_FUNCTIONS
52 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED)
54 #include <boost/move/detail/type_traits.hpp>
56 #if defined(BOOST_MOVE_ADDRESS_SANITIZER_ON)
57 #define BOOST_MOVE_TO_RV_CAST(RV_TYPE, ARG) reinterpret_cast<RV_TYPE>(ARG)
59 #define BOOST_MOVE_TO_RV_CAST(RV_TYPE, ARG) static_cast<RV_TYPE>(ARG)
62 //Move emulation rv breaks standard aliasing rules so add workarounds for some compilers
63 #if defined(__GNUC__) && (__GNUC__ >= 4) && \
65 defined(BOOST_GCC) || \
66 (defined(BOOST_INTEL) && (BOOST_INTEL_CXX_VERSION >= 1300)) \
68 #define BOOST_MOVE_ATTRIBUTE_MAY_ALIAS __attribute__((__may_alias__))
70 #define BOOST_MOVE_ATTRIBUTE_MAY_ALIAS
75 //////////////////////////////////////////////////////////////////////////////
79 //////////////////////////////////////////////////////////////////////////////
82 : public ::boost::move_detail::if_c
83 < ::boost::move_detail::is_class<T>::value
85 , ::boost::move_detail::nat
91 void operator=(rv const&);
92 } BOOST_MOVE_ATTRIBUTE_MAY_ALIAS;
95 //////////////////////////////////////////////////////////////////////////////
99 //////////////////////////////////////////////////////////////////////////////
101 namespace move_detail {
105 //Derive from integral constant because some Boost code assummes it has
106 //a "type" internal typedef
107 : integral_constant<bool, ::boost::move_detail::is_rv_impl<T>::value >
113 static const bool value = !is_rv<T>::value;
116 } //namespace move_detail {
118 //////////////////////////////////////////////////////////////////////////////
120 // has_move_emulation_enabled
122 //////////////////////////////////////////////////////////////////////////////
124 struct has_move_emulation_enabled
125 : ::boost::move_detail::has_move_emulation_enabled_impl<T>
129 struct has_move_emulation_disabled
131 static const bool value = !::boost::move_detail::has_move_emulation_enabled_impl<T>::value;
134 } //namespace boost {
136 #define BOOST_RV_REF(TYPE)\
137 ::boost::rv< TYPE >& \
140 #define BOOST_RV_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\
141 ::boost::rv< TYPE<ARG1, ARG2> >& \
144 #define BOOST_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\
145 ::boost::rv< TYPE<ARG1, ARG2, ARG3> >& \
148 #define BOOST_RV_REF_BEG\
152 #define BOOST_RV_REF_END\
156 #define BOOST_RV_REF_BEG_IF_CXX11 \
160 #define BOOST_RV_REF_END_IF_CXX11 \
164 #define BOOST_FWD_REF(TYPE)\
168 #define BOOST_COPY_ASSIGN_REF(TYPE)\
169 const ::boost::rv< TYPE >& \
172 #define BOOST_COPY_ASSIGN_REF_BEG \
176 #define BOOST_COPY_ASSIGN_REF_END \
180 #define BOOST_COPY_ASSIGN_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\
181 const ::boost::rv< TYPE<ARG1, ARG2> >& \
184 #define BOOST_COPY_ASSIGN_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\
185 const ::boost::rv< TYPE<ARG1, ARG2, ARG3> >& \
188 #define BOOST_CATCH_CONST_RLVALUE(TYPE)\
189 const ::boost::rv< TYPE >& \
193 namespace move_detail {
195 template <class Ret, class T>
196 inline typename ::boost::move_detail::enable_if_c
197 < ::boost::move_detail::is_lvalue_reference<Ret>::value ||
198 !::boost::has_move_emulation_enabled<T>::value
200 move_return(T& x) BOOST_NOEXCEPT
205 template <class Ret, class T>
206 inline typename ::boost::move_detail::enable_if_c
207 < !::boost::move_detail::is_lvalue_reference<Ret>::value &&
208 ::boost::has_move_emulation_enabled<T>::value
209 , ::boost::rv<T>&>::type
210 move_return(T& x) BOOST_NOEXCEPT
212 return *BOOST_MOVE_TO_RV_CAST(::boost::rv<T>*, ::boost::move_detail::addressof(x));
215 template <class Ret, class T>
216 inline typename ::boost::move_detail::enable_if_c
217 < !::boost::move_detail::is_lvalue_reference<Ret>::value &&
218 ::boost::has_move_emulation_enabled<T>::value
219 , ::boost::rv<T>&>::type
220 move_return(::boost::rv<T>& x) BOOST_NOEXCEPT
225 } //namespace move_detail {
226 } //namespace boost {
228 #define BOOST_MOVE_RET(RET_TYPE, REF)\
229 boost::move_detail::move_return< RET_TYPE >(REF)
232 #define BOOST_MOVE_BASE(BASE_TYPE, ARG) \
233 ::boost::move((BASE_TYPE&)(ARG))
236 //////////////////////////////////////////////////////////////////////////////
238 // BOOST_MOVABLE_BUT_NOT_COPYABLE
240 //////////////////////////////////////////////////////////////////////////////
241 #define BOOST_MOVABLE_BUT_NOT_COPYABLE(TYPE)\
242 BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE)\
244 operator ::boost::rv<TYPE>&() \
245 { return *BOOST_MOVE_TO_RV_CAST(::boost::rv<TYPE>*, this); }\
246 operator const ::boost::rv<TYPE>&() const \
247 { return *BOOST_MOVE_TO_RV_CAST(const ::boost::rv<TYPE>*, this); }\
251 //////////////////////////////////////////////////////////////////////////////
253 // BOOST_COPYABLE_AND_MOVABLE
255 //////////////////////////////////////////////////////////////////////////////
257 #define BOOST_COPYABLE_AND_MOVABLE(TYPE)\
259 TYPE& operator=(TYPE &t)\
260 { this->operator=(const_cast<const TYPE &>(t)); return *this;}\
262 operator ::boost::rv<TYPE>&() \
263 { return *BOOST_MOVE_TO_RV_CAST(::boost::rv<TYPE>*, this); }\
264 operator const ::boost::rv<TYPE>&() const \
265 { return *BOOST_MOVE_TO_RV_CAST(const ::boost::rv<TYPE>*, this); }\
269 #define BOOST_COPYABLE_AND_MOVABLE_ALT(TYPE)\
271 operator ::boost::rv<TYPE>&() \
272 { return *BOOST_MOVE_TO_RV_CAST(::boost::rv<TYPE>*, this); }\
273 operator const ::boost::rv<TYPE>&() const \
274 { return *BOOST_MOVE_TO_RV_CAST(const ::boost::rv<TYPE>*, this); }\
279 namespace move_detail{
283 { typedef const T &type; };
286 struct forward_type< boost::rv<T> >
291 #else //BOOST_NO_CXX11_RVALUE_REFERENCES
293 //! This macro marks a type as movable but not copyable, disabling copy construction
294 //! and assignment. The user will need to write a move constructor/assignment as explained
295 //! in the documentation to fully write a movable but not copyable class.
296 #define BOOST_MOVABLE_BUT_NOT_COPYABLE(TYPE)\
297 BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE)\
299 typedef int boost_move_emulation_t;\
302 //! This macro marks a type as copyable and movable.
303 //! The user will need to write a move constructor/assignment and a copy assignment
304 //! as explained in the documentation to fully write a copyable and movable class.
305 #define BOOST_COPYABLE_AND_MOVABLE(TYPE)\
308 #if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
309 #define BOOST_COPYABLE_AND_MOVABLE_ALT(TYPE)\
311 #endif //#if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
315 //!This trait yields to a compile-time true boolean if T was marked as
316 //!BOOST_MOVABLE_BUT_NOT_COPYABLE or BOOST_COPYABLE_AND_MOVABLE and
317 //!rvalue references are not available on the platform. False otherwise.
319 struct has_move_emulation_enabled
321 static const bool value = false;
325 struct has_move_emulation_disabled
327 static const bool value = true;
332 //!This macro is used to achieve portable syntax in move
333 //!constructors and assignments for classes marked as
334 //!BOOST_COPYABLE_AND_MOVABLE or BOOST_MOVABLE_BUT_NOT_COPYABLE
335 #define BOOST_RV_REF(TYPE)\
339 //!This macro is used to achieve portable syntax in move
340 //!constructors and assignments for template classes marked as
341 //!BOOST_COPYABLE_AND_MOVABLE or BOOST_MOVABLE_BUT_NOT_COPYABLE.
342 //!As macros have problems with comma-separated template arguments,
343 //!the template argument must be preceded with BOOST_RV_REF_BEG
344 //!and ended with BOOST_RV_REF_END
345 #define BOOST_RV_REF_BEG\
349 //!This macro is used to achieve portable syntax in move
350 //!constructors and assignments for template classes marked as
351 //!BOOST_COPYABLE_AND_MOVABLE or BOOST_MOVABLE_BUT_NOT_COPYABLE.
352 //!As macros have problems with comma-separated template arguments,
353 //!the template argument must be preceded with BOOST_RV_REF_BEG
354 //!and ended with BOOST_RV_REF_END
355 #define BOOST_RV_REF_END\
359 //!This macro expands to BOOST_RV_REF_BEG if BOOST_NO_CXX11_RVALUE_REFERENCES
360 //!is not defined, empty otherwise
361 #define BOOST_RV_REF_BEG_IF_CXX11 \
365 //!This macro expands to BOOST_RV_REF_END if BOOST_NO_CXX11_RVALUE_REFERENCES
366 //!is not defined, empty otherwise
367 #define BOOST_RV_REF_END_IF_CXX11 \
371 //!This macro is used to achieve portable syntax in copy
372 //!assignment for classes marked as BOOST_COPYABLE_AND_MOVABLE.
373 #define BOOST_COPY_ASSIGN_REF(TYPE)\
377 //! This macro is used to implement portable perfect forwarding
378 //! as explained in the documentation.
379 #define BOOST_FWD_REF(TYPE)\
383 #if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
385 #define BOOST_RV_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\
386 TYPE<ARG1, ARG2> && \
389 #define BOOST_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\
390 TYPE<ARG1, ARG2, ARG3> && \
393 #define BOOST_COPY_ASSIGN_REF_BEG \
397 #define BOOST_COPY_ASSIGN_REF_END \
401 #define BOOST_COPY_ASSIGN_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\
402 const TYPE<ARG1, ARG2> & \
405 #define BOOST_COPY_ASSIGN_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\
406 const TYPE<ARG1, ARG2, ARG3>& \
409 #define BOOST_CATCH_CONST_RLVALUE(TYPE)\
413 #endif //#if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
415 #if !defined(BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG) || defined(BOOST_MOVE_DOXYGEN_INVOKED)
417 //!This macro is used to achieve portable move return semantics.
418 //!The C++11 Standard allows implicit move returns when the object to be returned
419 //!is designated by a lvalue and:
420 //! - The criteria for elision of a copy operation are met OR
421 //! - The criteria would be met save for the fact that the source object is a function parameter
423 //!For C++11 conforming compilers this macros only yields to REF:
424 //! <code>return BOOST_MOVE_RET(RET_TYPE, REF);</code> -> <code>return REF;</code>
426 //!For compilers without rvalue references
427 //!this macro does an explicit move if the move emulation is activated
428 //!and the return type (RET_TYPE) is not a reference.
430 //!For non-conforming compilers with rvalue references like Visual 2010 & 2012,
431 //!an explicit move is performed if RET_TYPE is not a reference.
433 //! <b>Caution</b>: When using this macro in non-conforming or C++03
434 //!compilers, a move will be performed even if the C++11 standard does not allow it
435 //!(e.g. returning a static variable). The user is responsible for using this macro
436 //!only to return local objects that met C++11 criteria.
437 #define BOOST_MOVE_RET(RET_TYPE, REF)\
441 #else //!defined(BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG) || defined(BOOST_MOVE_DOXYGEN_INVOKED)
443 #include <boost/move/detail/meta_utils.hpp>
446 namespace move_detail {
448 template <class Ret, class T>
449 inline typename ::boost::move_detail::enable_if_c
450 < ::boost::move_detail::is_lvalue_reference<Ret>::value
452 move_return(T& x) BOOST_NOEXCEPT
457 template <class Ret, class T>
458 inline typename ::boost::move_detail::enable_if_c
459 < !::boost::move_detail::is_lvalue_reference<Ret>::value
461 move_return(T&& t) BOOST_NOEXCEPT
463 return static_cast< Ret&& >(t);
466 } //namespace move_detail {
467 } //namespace boost {
469 #define BOOST_MOVE_RET(RET_TYPE, REF)\
470 boost::move_detail::move_return< RET_TYPE >(REF)
473 #endif //!defined(BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG) || defined(BOOST_MOVE_DOXYGEN_INVOKED)
475 //!This macro is used to achieve portable optimal move constructors.
477 //!When implementing the move constructor, in C++03 compilers the moved-from argument must be
478 //!cast to the base type before calling `::boost::move()` due to rvalue reference limitations.
480 //!In C++11 compilers the cast from a rvalue reference of a derived type to a rvalue reference of
481 //!a base type is implicit.
482 #define BOOST_MOVE_BASE(BASE_TYPE, ARG) \
483 ::boost::move((BASE_TYPE&)(ARG))
487 namespace move_detail {
489 template< class T> struct forward_type { typedef T type; };
493 #endif //BOOST_NO_CXX11_RVALUE_REFERENCES
495 #include <boost/move/detail/config_end.hpp>
497 #endif //#ifndef BOOST_MOVE_CORE_HPP