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>
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) \
38 TYPE& operator=(TYPE &);\
40 typedef int boost_move_no_copy_constructor_or_assign; \
44 #define BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE) \
46 TYPE(TYPE const &) = delete;\
47 TYPE& operator=(TYPE const &) = delete;\
49 typedef int boost_move_no_copy_constructor_or_assign; \
52 #endif //BOOST_NO_CXX11_DELETED_FUNCTIONS
56 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED)
58 #include <boost/move/detail/type_traits.hpp>
60 #if defined(BOOST_MOVE_ADDRESS_SANITIZER_ON)
61 #define BOOST_MOVE_TO_RV_CAST(RV_TYPE, ARG) reinterpret_cast<RV_TYPE>(ARG)
63 #define BOOST_MOVE_TO_RV_CAST(RV_TYPE, ARG) static_cast<RV_TYPE>(ARG)
66 //Move emulation rv breaks standard aliasing rules so add workarounds for some compilers
67 #if defined(__GNUC__) && (__GNUC__ >= 4) && \
69 defined(BOOST_GCC) || \
70 (defined(BOOST_INTEL) && (BOOST_INTEL_CXX_VERSION >= 1300)) \
72 #define BOOST_MOVE_ATTRIBUTE_MAY_ALIAS __attribute__((__may_alias__))
74 #define BOOST_MOVE_ATTRIBUTE_MAY_ALIAS
79 //////////////////////////////////////////////////////////////////////////////
83 //////////////////////////////////////////////////////////////////////////////
86 : public ::boost::move_detail::if_c
87 < ::boost::move_detail::is_class<T>::value
89 , ::boost::move_detail::nat
95 void operator=(rv const&);
96 } BOOST_MOVE_ATTRIBUTE_MAY_ALIAS;
99 //////////////////////////////////////////////////////////////////////////////
103 //////////////////////////////////////////////////////////////////////////////
105 namespace move_detail {
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 >
117 static const bool value = !is_rv<T>::value;
120 } //namespace move_detail {
122 //////////////////////////////////////////////////////////////////////////////
124 // has_move_emulation_enabled
126 //////////////////////////////////////////////////////////////////////////////
128 struct has_move_emulation_enabled
129 : ::boost::move_detail::has_move_emulation_enabled_impl<T>
133 struct has_move_emulation_disabled
135 static const bool value = !::boost::move_detail::has_move_emulation_enabled_impl<T>::value;
138 } //namespace boost {
140 #define BOOST_RV_REF(TYPE)\
141 ::boost::rv< TYPE >& \
144 #define BOOST_RV_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\
145 ::boost::rv< TYPE<ARG1, ARG2> >& \
148 #define BOOST_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\
149 ::boost::rv< TYPE<ARG1, ARG2, ARG3> >& \
152 #define BOOST_RV_REF_BEG\
156 #define BOOST_RV_REF_END\
160 #define BOOST_RV_REF_BEG_IF_CXX11 \
164 #define BOOST_RV_REF_END_IF_CXX11 \
168 #define BOOST_FWD_REF(TYPE)\
172 #define BOOST_COPY_ASSIGN_REF(TYPE)\
173 const ::boost::rv< TYPE >& \
176 #define BOOST_COPY_ASSIGN_REF_BEG \
180 #define BOOST_COPY_ASSIGN_REF_END \
184 #define BOOST_COPY_ASSIGN_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\
185 const ::boost::rv< TYPE<ARG1, ARG2> >& \
188 #define BOOST_COPY_ASSIGN_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\
189 const ::boost::rv< TYPE<ARG1, ARG2, ARG3> >& \
192 #define BOOST_CATCH_CONST_RLVALUE(TYPE)\
193 const ::boost::rv< TYPE >& \
197 namespace move_detail {
199 template <class Ret, class T>
200 BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
201 < ::boost::move_detail::is_lvalue_reference<Ret>::value ||
202 !::boost::has_move_emulation_enabled<T>::value
204 move_return(T& x) BOOST_NOEXCEPT
209 template <class Ret, class T>
210 BOOST_MOVE_FORCEINLINE 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
216 return *BOOST_MOVE_TO_RV_CAST(::boost::rv<T>*, ::boost::move_detail::addressof(x));
219 template <class Ret, class T>
220 BOOST_MOVE_FORCEINLINE 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
229 } //namespace move_detail {
230 } //namespace boost {
232 #define BOOST_MOVE_RET(RET_TYPE, REF)\
233 boost::move_detail::move_return< RET_TYPE >(REF)
236 #define BOOST_MOVE_BASE(BASE_TYPE, ARG) \
237 ::boost::move((BASE_TYPE&)(ARG))
240 //////////////////////////////////////////////////////////////////////////////
242 // BOOST_MOVABLE_BUT_NOT_COPYABLE
244 //////////////////////////////////////////////////////////////////////////////
245 #define BOOST_MOVABLE_BUT_NOT_COPYABLE(TYPE)\
246 BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE)\
248 BOOST_MOVE_FORCEINLINE operator ::boost::rv<TYPE>&() \
249 { return *BOOST_MOVE_TO_RV_CAST(::boost::rv<TYPE>*, this); }\
250 BOOST_MOVE_FORCEINLINE operator const ::boost::rv<TYPE>&() const \
251 { return *BOOST_MOVE_TO_RV_CAST(const ::boost::rv<TYPE>*, this); }\
255 //////////////////////////////////////////////////////////////////////////////
257 // BOOST_COPYABLE_AND_MOVABLE
259 //////////////////////////////////////////////////////////////////////////////
261 #define BOOST_COPYABLE_AND_MOVABLE(TYPE)\
263 TYPE& operator=(TYPE &t)\
264 { this->operator=(const_cast<const TYPE &>(t)); return *this;}\
266 BOOST_MOVE_FORCEINLINE operator ::boost::rv<TYPE>&() \
267 { return *BOOST_MOVE_TO_RV_CAST(::boost::rv<TYPE>*, this); }\
268 BOOST_MOVE_FORCEINLINE operator const ::boost::rv<TYPE>&() const \
269 { return *BOOST_MOVE_TO_RV_CAST(const ::boost::rv<TYPE>*, this); }\
273 #define BOOST_COPYABLE_AND_MOVABLE_ALT(TYPE)\
275 BOOST_MOVE_FORCEINLINE operator ::boost::rv<TYPE>&() \
276 { return *BOOST_MOVE_TO_RV_CAST(::boost::rv<TYPE>*, this); }\
277 BOOST_MOVE_FORCEINLINE operator const ::boost::rv<TYPE>&() const \
278 { return *BOOST_MOVE_TO_RV_CAST(const ::boost::rv<TYPE>*, this); }\
283 namespace move_detail{
287 { typedef const T &type; };
290 struct forward_type< boost::rv<T> >
295 #else //BOOST_NO_CXX11_RVALUE_REFERENCES
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)\
303 typedef int boost_move_emulation_t;\
307 //! This macro marks a type as copyable and movable.
308 //! The user will need to write a move constructor/assignment and a copy assignment
309 //! as explained in the documentation to fully write a copyable and movable class.
310 #define BOOST_COPYABLE_AND_MOVABLE(TYPE)\
313 #if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
314 #define BOOST_COPYABLE_AND_MOVABLE_ALT(TYPE)\
316 #endif //#if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
320 //!This trait yields to a compile-time true boolean if T was marked as
321 //!BOOST_MOVABLE_BUT_NOT_COPYABLE or BOOST_COPYABLE_AND_MOVABLE and
322 //!rvalue references are not available on the platform. False otherwise.
324 struct has_move_emulation_enabled
326 static const bool value = false;
330 struct has_move_emulation_disabled
332 static const bool value = true;
337 //!This macro is used to achieve portable syntax in move
338 //!constructors and assignments for classes marked as
339 //!BOOST_COPYABLE_AND_MOVABLE or BOOST_MOVABLE_BUT_NOT_COPYABLE
340 #define BOOST_RV_REF(TYPE)\
344 //!This macro is used to achieve portable syntax in move
345 //!constructors and assignments for template classes marked as
346 //!BOOST_COPYABLE_AND_MOVABLE or BOOST_MOVABLE_BUT_NOT_COPYABLE.
347 //!As macros have problems with comma-separated template arguments,
348 //!the template argument must be preceded with BOOST_RV_REF_BEG
349 //!and ended with BOOST_RV_REF_END
350 #define BOOST_RV_REF_BEG\
354 //!This macro is used to achieve portable syntax in move
355 //!constructors and assignments for template classes marked as
356 //!BOOST_COPYABLE_AND_MOVABLE or BOOST_MOVABLE_BUT_NOT_COPYABLE.
357 //!As macros have problems with comma-separated template arguments,
358 //!the template argument must be preceded with BOOST_RV_REF_BEG
359 //!and ended with BOOST_RV_REF_END
360 #define BOOST_RV_REF_END\
364 //!This macro expands to BOOST_RV_REF_BEG if BOOST_NO_CXX11_RVALUE_REFERENCES
365 //!is not defined, empty otherwise
366 #define BOOST_RV_REF_BEG_IF_CXX11 \
370 //!This macro expands to BOOST_RV_REF_END if BOOST_NO_CXX11_RVALUE_REFERENCES
371 //!is not defined, empty otherwise
372 #define BOOST_RV_REF_END_IF_CXX11 \
376 //!This macro is used to achieve portable syntax in copy
377 //!assignment for classes marked as BOOST_COPYABLE_AND_MOVABLE.
378 #define BOOST_COPY_ASSIGN_REF(TYPE)\
382 //! This macro is used to implement portable perfect forwarding
383 //! as explained in the documentation.
384 #define BOOST_FWD_REF(TYPE)\
388 #if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
390 #define BOOST_RV_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\
391 TYPE<ARG1, ARG2> && \
394 #define BOOST_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\
395 TYPE<ARG1, ARG2, ARG3> && \
398 #define BOOST_COPY_ASSIGN_REF_BEG \
402 #define BOOST_COPY_ASSIGN_REF_END \
406 #define BOOST_COPY_ASSIGN_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\
407 const TYPE<ARG1, ARG2> & \
410 #define BOOST_COPY_ASSIGN_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\
411 const TYPE<ARG1, ARG2, ARG3>& \
414 #define BOOST_CATCH_CONST_RLVALUE(TYPE)\
418 #endif //#if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
420 #if !defined(BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG) || defined(BOOST_MOVE_DOXYGEN_INVOKED)
422 //!This macro is used to achieve portable move return semantics.
423 //!The C++11 Standard allows implicit move returns when the object to be returned
424 //!is designated by a lvalue and:
425 //! - The criteria for elision of a copy operation are met OR
426 //! - The criteria would be met save for the fact that the source object is a function parameter
428 //!For C++11 conforming compilers this macros only yields to REF:
429 //! <code>return BOOST_MOVE_RET(RET_TYPE, REF);</code> -> <code>return REF;</code>
431 //!For compilers without rvalue references
432 //!this macro does an explicit move if the move emulation is activated
433 //!and the return type (RET_TYPE) is not a reference.
435 //!For non-conforming compilers with rvalue references like Visual 2010 & 2012,
436 //!an explicit move is performed if RET_TYPE is not a reference.
438 //! <b>Caution</b>: When using this macro in non-conforming or C++03
439 //!compilers, a move will be performed even if the C++11 standard does not allow it
440 //!(e.g. returning a static variable). The user is responsible for using this macro
441 //!only to return local objects that met C++11 criteria.
442 #define BOOST_MOVE_RET(RET_TYPE, REF)\
446 #else //!defined(BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG) || defined(BOOST_MOVE_DOXYGEN_INVOKED)
448 #include <boost/move/detail/meta_utils.hpp>
451 namespace move_detail {
453 template <class Ret, class T>
454 BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
455 < ::boost::move_detail::is_lvalue_reference<Ret>::value
457 move_return(T& x) BOOST_NOEXCEPT
462 template <class Ret, class T>
463 BOOST_MOVE_FORCEINLINE typename ::boost::move_detail::enable_if_c
464 < !::boost::move_detail::is_lvalue_reference<Ret>::value
466 move_return(T&& t) BOOST_NOEXCEPT
468 return static_cast< Ret&& >(t);
471 } //namespace move_detail {
472 } //namespace boost {
474 #define BOOST_MOVE_RET(RET_TYPE, REF)\
475 boost::move_detail::move_return< RET_TYPE >(REF)
478 #endif //!defined(BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG) || defined(BOOST_MOVE_DOXYGEN_INVOKED)
480 //!This macro is used to achieve portable optimal move constructors.
482 //!When implementing the move constructor, in C++03 compilers the moved-from argument must be
483 //!cast to the base type before calling `::boost::move()` due to rvalue reference limitations.
485 //!In C++11 compilers the cast from a rvalue reference of a derived type to a rvalue reference of
486 //!a base type is implicit.
487 #define BOOST_MOVE_BASE(BASE_TYPE, ARG) \
488 ::boost::move((BASE_TYPE&)(ARG))
492 namespace move_detail {
494 template< class T> struct forward_type { typedef T type; };
498 #endif //BOOST_NO_CXX11_RVALUE_REFERENCES
500 #include <boost/move/detail/config_end.hpp>
502 #endif //#ifndef BOOST_MOVE_CORE_HPP