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