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