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 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 203 , T&>::type move_return(T & x)204 move_return(T& x) BOOST_NOEXCEPT 205 { 206 return x; 207 } 208 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 move_return(T & x)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 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 move_return(::boost::rv<T> & x)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 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); }\ 252 private:\ 253 // 254 255 ////////////////////////////////////////////////////////////////////////////// 256 // 257 // BOOST_COPYABLE_AND_MOVABLE 258 // 259 ////////////////////////////////////////////////////////////////////////////// 260 261 #define BOOST_COPYABLE_AND_MOVABLE(TYPE)\ 262 public:\ 263 BOOST_MOVE_FORCEINLINE TYPE& operator=(TYPE &t)\ 264 { this->operator=(const_cast<const TYPE&>(t)); return *this;}\ 265 public:\ 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); }\ 270 private:\ 271 // 272 273 #define BOOST_COPYABLE_AND_MOVABLE_ALT(TYPE)\ 274 public:\ 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); }\ 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 private:\ 305 // 306 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)\ 311 // 312 313 #if !defined(BOOST_MOVE_DOXYGEN_INVOKED) 314 #define BOOST_COPYABLE_AND_MOVABLE_ALT(TYPE)\ 315 // 316 #endif //#if !defined(BOOST_MOVE_DOXYGEN_INVOKED) 317 318 namespace boost { 319 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. 323 template<class T> 324 struct has_move_emulation_enabled 325 { 326 static const bool value = false; 327 }; 328 329 template<class T> 330 struct has_move_emulation_disabled 331 { 332 static const bool value = true; 333 }; 334 335 } //namespace boost{ 336 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)\ 341 TYPE && \ 342 // 343 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\ 351 \ 352 // 353 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\ 361 && \ 362 // 363 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 \ 367 BOOST_RV_REF_BEG \ 368 // 369 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 \ 373 BOOST_RV_REF_END \ 374 // 375 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)\ 379 const TYPE & \ 380 // 381 382 //! This macro is used to implement portable perfect forwarding 383 //! as explained in the documentation. 384 #define BOOST_FWD_REF(TYPE)\ 385 TYPE && \ 386 // 387 388 #if !defined(BOOST_MOVE_DOXYGEN_INVOKED) 389 390 #define BOOST_RV_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\ 391 TYPE<ARG1, ARG2> && \ 392 // 393 394 #define BOOST_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ 395 TYPE<ARG1, ARG2, ARG3> && \ 396 // 397 398 #define BOOST_COPY_ASSIGN_REF_BEG \ 399 const \ 400 // 401 402 #define BOOST_COPY_ASSIGN_REF_END \ 403 & \ 404 // 405 406 #define BOOST_COPY_ASSIGN_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\ 407 const TYPE<ARG1, ARG2> & \ 408 // 409 410 #define BOOST_COPY_ASSIGN_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\ 411 const TYPE<ARG1, ARG2, ARG3>& \ 412 // 413 414 #define BOOST_CATCH_CONST_RLVALUE(TYPE)\ 415 const TYPE & \ 416 // 417 418 #endif //#if !defined(BOOST_MOVE_DOXYGEN_INVOKED) 419 420 #if !defined(BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG) || defined(BOOST_MOVE_DOXYGEN_INVOKED) 421 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 427 //! 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> 430 //! 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. 434 //! 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. 437 //! 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)\ 443 REF 444 // 445 446 #else //!defined(BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG) || defined(BOOST_MOVE_DOXYGEN_INVOKED) 447 448 #include <boost/move/detail/meta_utils.hpp> 449 450 namespace boost { 451 namespace move_detail { 452 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 456 , T&>::type move_return(T & x)457 move_return(T& x) BOOST_NOEXCEPT 458 { 459 return x; 460 } 461 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 465 , Ret && >::type move_return(T && t)466 move_return(T&& t) BOOST_NOEXCEPT 467 { 468 return static_cast< Ret&& >(t); 469 } 470 471 } //namespace move_detail { 472 } //namespace boost { 473 474 #define BOOST_MOVE_RET(RET_TYPE, REF)\ 475 boost::move_detail::move_return< RET_TYPE >(REF) 476 // 477 478 #endif //!defined(BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG) || defined(BOOST_MOVE_DOXYGEN_INVOKED) 479 480 //!This macro is used to achieve portable optimal move constructors. 481 //! 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. 484 //! 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)) 489 // 490 491 namespace boost { 492 namespace move_detail { 493 494 template< class T> struct forward_type { typedef T type; }; 495 496 }} 497 498 #endif //BOOST_NO_CXX11_RVALUE_REFERENCES 499 500 #include <boost/move/detail/config_end.hpp> 501 502 #endif //#ifndef BOOST_MOVE_CORE_HPP 503