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