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