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 //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) \
34       private:\
35       TYPE(TYPE &);\
36       TYPE& operator=(TYPE &);\
37       public:\
38       typedef int boost_move_no_copy_constructor_or_assign; \
39       private:\
40    //
41 #else
42    #define BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE) \
43       public:\
44       TYPE(TYPE const &) = delete;\
45       TYPE& operator=(TYPE const &) = delete;\
46       public:\
47       typedef int boost_move_no_copy_constructor_or_assign; \
48       private:\
49    //
50 #endif   //BOOST_NO_CXX11_DELETED_FUNCTIONS
51 
52 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED)
53 
54    #include <boost/move/detail/type_traits.hpp>
55 
56    #if defined(BOOST_MOVE_ADDRESS_SANITIZER_ON)
57       #define BOOST_MOVE_TO_RV_CAST(RV_TYPE, ARG) reinterpret_cast<RV_TYPE>(ARG)
58    #else
59       #define BOOST_MOVE_TO_RV_CAST(RV_TYPE, ARG) static_cast<RV_TYPE>(ARG)
60    #endif
61 
62    //Move emulation rv breaks standard aliasing rules so add workarounds for some compilers
63    #if defined(__GNUC__) && (__GNUC__ >= 4) && \
64       (\
65          defined(BOOST_GCC) ||   \
66          (defined(BOOST_INTEL) && (BOOST_INTEL_CXX_VERSION >= 1300)) \
67       )
68       #define BOOST_MOVE_ATTRIBUTE_MAY_ALIAS __attribute__((__may_alias__))
69    #else
70       #define BOOST_MOVE_ATTRIBUTE_MAY_ALIAS
71    #endif
72 
73    namespace boost {
74 
75    //////////////////////////////////////////////////////////////////////////////
76    //
77    //                            struct rv
78    //
79    //////////////////////////////////////////////////////////////////////////////
80    template <class T>
81    class rv
82       : public ::boost::move_detail::if_c
83          < ::boost::move_detail::is_class<T>::value
84          , T
85          , ::boost::move_detail::nat
86          >::type
87    {
88       rv();
89       ~rv() throw();
90       rv(rv const&);
91       void operator=(rv const&);
92    } BOOST_MOVE_ATTRIBUTE_MAY_ALIAS;
93 
94 
95    //////////////////////////////////////////////////////////////////////////////
96    //
97    //                            is_rv
98    //
99    //////////////////////////////////////////////////////////////////////////////
100 
101    namespace move_detail {
102 
103    template <class T>
104    struct is_rv
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 >
108    {};
109 
110    template <class T>
111    struct is_not_rv
112    {
113       static const bool value = !is_rv<T>::value;
114    };
115 
116    }  //namespace move_detail {
117 
118    //////////////////////////////////////////////////////////////////////////////
119    //
120    //                               has_move_emulation_enabled
121    //
122    //////////////////////////////////////////////////////////////////////////////
123    template<class T>
124    struct has_move_emulation_enabled
125       : ::boost::move_detail::has_move_emulation_enabled_impl<T>
126    {};
127 
128    template<class T>
129    struct has_move_emulation_disabled
130    {
131       static const bool value = !::boost::move_detail::has_move_emulation_enabled_impl<T>::value;
132    };
133 
134    }  //namespace boost {
135 
136    #define BOOST_RV_REF(TYPE)\
137       ::boost::rv< TYPE >& \
138    //
139 
140    #define BOOST_RV_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\
141       ::boost::rv< TYPE<ARG1, ARG2> >& \
142    //
143 
144    #define BOOST_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\
145       ::boost::rv< TYPE<ARG1, ARG2, ARG3> >& \
146    //
147 
148    #define BOOST_RV_REF_BEG\
149       ::boost::rv<   \
150    //
151 
152    #define BOOST_RV_REF_END\
153       >& \
154    //
155 
156    #define BOOST_RV_REF_BEG_IF_CXX11 \
157       \
158    //
159 
160    #define BOOST_RV_REF_END_IF_CXX11 \
161       \
162    //
163 
164    #define BOOST_FWD_REF(TYPE)\
165       const TYPE & \
166    //
167 
168    #define BOOST_COPY_ASSIGN_REF(TYPE)\
169       const ::boost::rv< TYPE >& \
170    //
171 
172    #define BOOST_COPY_ASSIGN_REF_BEG \
173       const ::boost::rv<  \
174    //
175 
176    #define BOOST_COPY_ASSIGN_REF_END \
177       >& \
178    //
179 
180    #define BOOST_COPY_ASSIGN_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\
181       const ::boost::rv< TYPE<ARG1, ARG2> >& \
182    //
183 
184    #define BOOST_COPY_ASSIGN_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\
185       const ::boost::rv< TYPE<ARG1, ARG2, ARG3> >& \
186    //
187 
188    #define BOOST_CATCH_CONST_RLVALUE(TYPE)\
189       const ::boost::rv< TYPE >& \
190    //
191 
192    namespace boost {
193    namespace move_detail {
194 
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
199       , T&>::type
move_return(T & x)200          move_return(T& x) BOOST_NOEXCEPT
201    {
202       return x;
203    }
204 
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
move_return(T & x)210          move_return(T& x) BOOST_NOEXCEPT
211    {
212       return *BOOST_MOVE_TO_RV_CAST(::boost::rv<T>*, ::boost::move_detail::addressof(x));
213    }
214 
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
move_return(::boost::rv<T> & x)220          move_return(::boost::rv<T>& x) BOOST_NOEXCEPT
221    {
222       return x;
223    }
224 
225    }  //namespace move_detail {
226    }  //namespace boost {
227 
228    #define BOOST_MOVE_RET(RET_TYPE, REF)\
229       boost::move_detail::move_return< RET_TYPE >(REF)
230    //
231 
232    #define BOOST_MOVE_BASE(BASE_TYPE, ARG) \
233       ::boost::move((BASE_TYPE&)(ARG))
234    //
235 
236    //////////////////////////////////////////////////////////////////////////////
237    //
238    //                         BOOST_MOVABLE_BUT_NOT_COPYABLE
239    //
240    //////////////////////////////////////////////////////////////////////////////
241    #define BOOST_MOVABLE_BUT_NOT_COPYABLE(TYPE)\
242       BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE)\
243       public:\
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);  }\
248       private:\
249    //
250 
251    //////////////////////////////////////////////////////////////////////////////
252    //
253    //                         BOOST_COPYABLE_AND_MOVABLE
254    //
255    //////////////////////////////////////////////////////////////////////////////
256 
257    #define BOOST_COPYABLE_AND_MOVABLE(TYPE)\
258       public:\
259       TYPE& operator=(TYPE &t)\
260       {  this->operator=(const_cast<const TYPE &>(t)); return *this;}\
261       public:\
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);  }\
266       private:\
267    //
268 
269    #define BOOST_COPYABLE_AND_MOVABLE_ALT(TYPE)\
270       public:\
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);  }\
275       private:\
276    //
277 
278    namespace boost{
279    namespace move_detail{
280 
281    template< class T>
282    struct forward_type
283    { typedef const T &type; };
284 
285    template< class T>
286    struct forward_type< boost::rv<T> >
287    { typedef T type; };
288 
289    }}
290 
291 #else    //BOOST_NO_CXX11_RVALUE_REFERENCES
292 
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)\
298       public:\
299       typedef int boost_move_emulation_t;\
300    //
301 
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)\
306    //
307 
308    #if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
309    #define BOOST_COPYABLE_AND_MOVABLE_ALT(TYPE)\
310    //
311    #endif   //#if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
312 
313    namespace boost {
314 
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.
318    template<class T>
319    struct has_move_emulation_enabled
320    {
321       static const bool value = false;
322    };
323 
324    template<class T>
325    struct has_move_emulation_disabled
326    {
327       static const bool value = true;
328    };
329 
330    }  //namespace boost{
331 
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)\
336       TYPE && \
337    //
338 
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\
346          \
347    //
348 
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\
356       && \
357    //
358 
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 \
362       BOOST_RV_REF_BEG \
363    //
364 
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 \
368       BOOST_RV_REF_END \
369    //
370 
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)\
374       const TYPE & \
375    //
376 
377    //! This macro is used to implement portable perfect forwarding
378    //! as explained in the documentation.
379    #define BOOST_FWD_REF(TYPE)\
380       TYPE && \
381    //
382 
383    #if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
384 
385    #define BOOST_RV_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\
386       TYPE<ARG1, ARG2> && \
387    //
388 
389    #define BOOST_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\
390       TYPE<ARG1, ARG2, ARG3> && \
391    //
392 
393    #define BOOST_COPY_ASSIGN_REF_BEG \
394       const \
395    //
396 
397    #define BOOST_COPY_ASSIGN_REF_END \
398       & \
399    //
400 
401    #define BOOST_COPY_ASSIGN_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\
402       const TYPE<ARG1, ARG2> & \
403    //
404 
405    #define BOOST_COPY_ASSIGN_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\
406       const TYPE<ARG1, ARG2, ARG3>& \
407    //
408 
409    #define BOOST_CATCH_CONST_RLVALUE(TYPE)\
410       const TYPE & \
411    //
412 
413    #endif   //#if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
414 
415    #if !defined(BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG) || defined(BOOST_MOVE_DOXYGEN_INVOKED)
416 
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
422       //!
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>
425       //!
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.
429       //!
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.
432       //!
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)\
438          REF
439       //
440 
441    #else //!defined(BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG) || defined(BOOST_MOVE_DOXYGEN_INVOKED)
442 
443       #include <boost/move/detail/meta_utils.hpp>
444 
445       namespace boost {
446       namespace move_detail {
447 
448       template <class Ret, class T>
449       inline typename ::boost::move_detail::enable_if_c
450          <  ::boost::move_detail::is_lvalue_reference<Ret>::value
451          , T&>::type
move_return(T & x)452             move_return(T& x) BOOST_NOEXCEPT
453       {
454          return x;
455       }
456 
457       template <class Ret, class T>
458       inline typename ::boost::move_detail::enable_if_c
459          < !::boost::move_detail::is_lvalue_reference<Ret>::value
460          , Ret && >::type
move_return(T && t)461             move_return(T&& t) BOOST_NOEXCEPT
462       {
463          return static_cast< Ret&& >(t);
464       }
465 
466       }  //namespace move_detail {
467       }  //namespace boost {
468 
469       #define BOOST_MOVE_RET(RET_TYPE, REF)\
470          boost::move_detail::move_return< RET_TYPE >(REF)
471       //
472 
473    #endif   //!defined(BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG) || defined(BOOST_MOVE_DOXYGEN_INVOKED)
474 
475    //!This macro is used to achieve portable optimal move constructors.
476    //!
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.
479    //!
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))
484    //
485 
486    namespace boost {
487    namespace move_detail {
488 
489    template< class T> struct forward_type { typedef T type; };
490 
491    }}
492 
493 #endif   //BOOST_NO_CXX11_RVALUE_REFERENCES
494 
495 #include <boost/move/detail/config_end.hpp>
496 
497 #endif //#ifndef BOOST_MOVE_CORE_HPP
498