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