Ticket #7620: rvalue_move.patch
File rvalue_move.patch, 17.5 KB (added by , 10 years ago) |
---|
-
detail/backup_holder.hpp
13 13 #ifndef BOOST_VARIANT_DETAIL_BACKUP_HOLDER_HPP 14 14 #define BOOST_VARIANT_DETAIL_BACKUP_HOLDER_HPP 15 15 16 #include "boost/config.hpp" 16 17 #include "boost/assert.hpp" 17 18 18 19 namespace boost { … … 32 33 delete backup_; 33 34 } 34 35 35 explicit backup_holder(T* backup) 36 explicit backup_holder(T* backup) BOOST_NOEXCEPT 36 37 : backup_(backup) 37 38 { 38 39 } … … 53 54 return *this; 54 55 } 55 56 56 void swap(backup_holder& rhs) 57 void swap(backup_holder& rhs) BOOST_NOEXCEPT 57 58 { 58 59 T* tmp = rhs.backup_; 59 60 rhs.backup_ = this->backup_; … … 83 84 } 84 85 85 86 template <typename T> 86 void swap(backup_holder<T>& lhs, backup_holder<T>& rhs) 87 void swap(backup_holder<T>& lhs, backup_holder<T>& rhs) BOOST_NOEXCEPT 87 88 { 88 89 lhs.swap(rhs); 89 90 } -
detail/move.hpp
82 82 83 83 } // namespace detail 84 84 85 #ifdef BOOST_NO_RVALUE_REFERENCES 86 85 87 template <typename T> 86 88 inline 87 89 typename detail::move_type<T>::type … … 93 95 return move_t(source); 94 96 } 95 97 98 #else 99 100 using std::move; 101 102 #endif 103 96 104 ////////////////////////////////////////////////////////////////////////// 97 105 // class template return_t 98 106 // -
variant.hpp
51 51 #include "boost/type_traits/has_nothrow_copy.hpp" 52 52 #include "boost/type_traits/is_const.hpp" 53 53 #include "boost/type_traits/is_same.hpp" 54 #include "boost/type_traits/is_rvalue_reference.hpp" 54 55 #include "boost/utility/enable_if.hpp" 56 #include "boost/utility/declval.hpp" 55 57 #include "boost/variant/recursive_wrapper_fwd.hpp" 56 58 #include "boost/variant/static_visitor.hpp" 57 59 … … 338 340 339 341 public: // visitor interface 340 342 341 T& operator()(T& operand) const 343 T& operator()(T& operand) const BOOST_NOEXCEPT 342 344 { 343 345 return operand; 344 346 } … … 397 399 398 400 public: // structors 399 401 400 explicit copy_into(void* storage) 402 explicit copy_into(void* storage) BOOST_NOEXCEPT 401 403 : storage_(storage) 402 404 { 403 405 } … … 431 433 }; 432 434 433 435 /////////////////////////////////////////////////////////////////////////////// 436 // (detail) class move_into 437 // 438 // Internal visitor that moves the value it visits into the given buffer. 439 // 440 #ifndef BOOST_NO_RVALUE_REFERENCES 441 class move_into 442 : public static_visitor<> 443 { 444 private: // representation 445 446 void* storage_; 447 448 public: // structors 449 450 explicit move_into(void* storage) BOOST_NOEXCEPT 451 : storage_(storage) 452 { 453 } 454 455 public: // internal visitor interface 456 457 template <typename T> 458 BOOST_VARIANT_AUX_RETURN_VOID_TYPE 459 internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const 460 { 461 new(storage_) T( ::boost::detail::variant::move(operand.get()) ); 462 BOOST_VARIANT_AUX_RETURN_VOID; 463 } 464 465 template <typename T> 466 BOOST_VARIANT_AUX_RETURN_VOID_TYPE 467 internal_visit(T& operand, int) const BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(T(boost::declval<T>()))) 468 { 469 new(storage_) T(::boost::detail::variant::move(operand)); 470 BOOST_VARIANT_AUX_RETURN_VOID; 471 } 472 }; 473 #endif 474 475 /////////////////////////////////////////////////////////////////////////////// 434 476 // (detail) class assign_storage 435 477 // 436 478 // Internal visitor that assigns the given storage (which must be a … … 445 487 446 488 public: // structors 447 489 448 explicit assign_storage(const void* rhs_storage) 490 explicit assign_storage(const void* rhs_storage) BOOST_NOEXCEPT 449 491 : rhs_storage_(rhs_storage) 450 492 { 451 493 } … … 488 530 }; 489 531 490 532 /////////////////////////////////////////////////////////////////////////////// 533 // (detail) class move_storage 534 // 535 // Internal visitor that moves the given storage (which must be a 536 // constructed value of the same type) to the value it visits. 537 // 538 struct move_storage 539 : public static_visitor<> 540 { 541 private: // representation 542 543 void* rhs_storage_; 544 545 public: // structors 546 547 explicit move_storage(void* rhs_storage) BOOST_NOEXCEPT 548 : rhs_storage_(rhs_storage) 549 { 550 } 551 552 public: // internal visitor interfaces 553 554 template <typename T> 555 BOOST_VARIANT_AUX_RETURN_VOID_TYPE 556 internal_visit(backup_holder<T>& lhs_content, long) const 557 { 558 lhs_content.get() 559 = ::boost::detail::variant::move(static_cast<backup_holder<T>* >(rhs_storage_)->get()); 560 BOOST_VARIANT_AUX_RETURN_VOID; 561 } 562 563 template <typename T> 564 BOOST_VARIANT_AUX_RETURN_VOID_TYPE 565 internal_visit(const backup_holder<T>& lhs_content, long) const 566 { 567 lhs_content.get() 568 = ::boost::detail::variant::move(static_cast<backup_holder<T>* >(rhs_storage_)->get()); 569 BOOST_VARIANT_AUX_RETURN_VOID; 570 } 571 572 template <typename T> 573 BOOST_VARIANT_AUX_RETURN_VOID_TYPE 574 internal_visit(T& lhs_content, int) const 575 { 576 // NOTE TO USER : 577 // Compile error here indicates one of variant's bounded types does 578 // not meet the requirements of the Assignable concept. Thus, 579 // variant is not Assignable. 580 // 581 // Hint: Are any of the bounded types const-qualified or references? 582 // 583 lhs_content = ::boost::detail::variant::move(*static_cast<T* >(rhs_storage_)); 584 BOOST_VARIANT_AUX_RETURN_VOID; 585 } 586 587 }; 588 589 /////////////////////////////////////////////////////////////////////////////// 491 590 // (detail) class direct_assigner 492 591 // 493 592 // Generic static visitor that: if and only if the visited value is of the … … 504 603 505 604 public: // structors 506 605 507 explicit direct_assigner(const T& rhs) 606 explicit direct_assigner(const T& rhs) BOOST_NOEXCEPT 508 607 : rhs_(rhs) 509 608 { 510 609 } … … 520 619 } 521 620 522 621 template <typename U> 523 bool operator()(U&) 622 bool operator()(U&) BOOST_NOEXCEPT 524 623 { 525 624 return false; 526 625 } … … 560 659 }; 561 660 562 661 /////////////////////////////////////////////////////////////////////////////// 662 // (detail) class direct_mover 663 // 664 // Generic static visitor that: if and only if the visited value is of the 665 // specified type, move assigns the given value to the visited value and returns 666 // true; else returns false. 667 // 668 template <typename T> 669 class direct_mover 670 : public static_visitor<bool> 671 { 672 private: // representation 673 674 T& rhs_; 675 676 public: // structors 677 678 explicit direct_mover(T& rhs) BOOST_NOEXCEPT 679 : rhs_(rhs) 680 { 681 } 682 683 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) 684 685 public: // visitor interface 686 687 bool operator()(T& lhs) 688 { 689 lhs = ::boost::detail::variant::move(rhs_); 690 return true; 691 } 692 693 template <typename U> 694 bool operator()(U&) BOOST_NOEXCEPT 695 { 696 return false; 697 } 698 699 #else // MSVC6 700 701 public: // visitor interface 702 703 template <typename U> 704 bool operator()(U& lhs) 705 { 706 // MSVC6 can not use direct_mover class 707 return direct_assigner(rhs_)(lhs); 708 } 709 710 #endif // MSVC6 workaround 711 712 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600)) 713 private: 714 // silence MSVC warning C4512: assignment operator could not be generated 715 direct_mover& operator= (direct_mover const&); 716 #endif 717 }; 718 719 720 /////////////////////////////////////////////////////////////////////////////// 563 721 // (detail) class backup_assigner 564 722 // 565 723 // Internal visitor that "assigns" the given value to the visited value, … … 745 903 public: // visitor interfaces 746 904 747 905 template <typename T> 748 const std::type_info& operator()(const T&) const 906 const std::type_info& operator()(const T&) const BOOST_NOEXCEPT 749 907 { 750 908 return typeid(T); 751 909 } … … 772 930 773 931 public: // structors 774 932 775 explicit comparer(const Variant& lhs) 933 explicit comparer(const Variant& lhs) BOOST_NOEXCEPT 776 934 : lhs_(lhs) 777 935 { 778 936 } … … 844 1002 845 1003 public: // structors 846 1004 847 explicit invoke_visitor(Visitor& visitor) 1005 explicit invoke_visitor(Visitor& visitor) BOOST_NOEXCEPT 848 1006 : visitor_(visitor) 849 1007 { 850 1008 } … … 1170 1328 which_t which_; 1171 1329 storage_t storage_; 1172 1330 1173 void indicate_which(int which_arg) 1331 void indicate_which(int which_arg) BOOST_NOEXCEPT 1174 1332 { 1175 1333 which_ = static_cast<which_t>( which_arg ); 1176 1334 } 1177 1335 1178 void indicate_backup_which(int which_arg) 1336 void indicate_backup_which(int which_arg) BOOST_NOEXCEPT 1179 1337 { 1180 1338 which_ = static_cast<which_t>( -(which_arg + 1) ); 1181 1339 } 1182 1340 1183 1341 private: // helpers, for queries (below) 1184 1342 1185 bool using_backup() const 1343 bool using_backup() const BOOST_NOEXCEPT 1186 1344 { 1187 1345 return which_ < 0; 1188 1346 } 1189 1347 1190 1348 public: // queries 1191 1349 1192 int which() const 1350 int which() const BOOST_NOEXCEPT 1193 1351 { 1194 1352 // If using heap backup... 1195 1353 if (using_backup()) … … 1222 1380 destroy_content(); 1223 1381 } 1224 1382 1225 variant() 1383 variant() BOOST_NOEXCEPT_IF(boost::has_nothrow_constructor<internal_T0>::type::value) 1226 1384 { 1227 1385 // NOTE TO USER : 1228 1386 // Compile error from here indicates that the first bound … … 1244 1402 1245 1403 public: // structors 1246 1404 1247 explicit convert_copy_into(void* storage) 1405 explicit convert_copy_into(void* storage) BOOST_NOEXCEPT 1248 1406 : storage_(storage) 1249 1407 { 1250 1408 } … … 1454 1612 // ...and activate the *this's primary storage on success: 1455 1613 indicate_which(operand.which()); 1456 1614 } 1615 1616 #ifndef BOOST_NO_RVALUE_REFERENCES 1617 variant(variant&& operand) 1618 { 1619 // Move the value of operand into *this... 1620 detail::variant::move_into visitor( storage_.address() ); 1621 operand.internal_apply_visitor(visitor); 1457 1622 1623 // ...and activate the *this's primary storage on success: 1624 indicate_which(operand.which()); 1625 } 1626 #endif 1627 1458 1628 private: // helpers, for modifiers (below) 1459 1629 1460 1630 # if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) … … 1478 1648 1479 1649 public: // structors 1480 1650 1481 assigner(variant& lhs, int rhs_which) 1651 assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT 1482 1652 : lhs_(lhs) 1483 1653 , rhs_which_(rhs_which) 1484 1654 { … … 1605 1775 assigner& operator= (assigner const&); 1606 1776 #endif 1607 1777 }; 1608 1778 1609 1779 friend class assigner; 1780 1781 #ifndef BOOST_NO_RVALUE_REFERENCES 1782 // class move_assigner 1783 // 1784 // Internal visitor that "move assigns" the visited value to the given variant 1785 // by appropriate destruction and move-construction. 1786 // 1610 1787 1788 class move_assigner 1789 : public static_visitor<> 1790 { 1791 private: // representation 1792 1793 variant& lhs_; 1794 int rhs_which_; 1795 1796 public: // structors 1797 1798 move_assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT 1799 : lhs_(lhs) 1800 , rhs_which_(rhs_which) 1801 { 1802 } 1803 1804 private: // helpers, for internal visitor interface (below) 1805 1806 template <typename RhsT, typename B1, typename B2> 1807 void assign_impl( 1808 RhsT& rhs_content 1809 , mpl::true_// has_nothrow_copy 1810 , mpl::false_// has_nothrow_move_constructor 1811 , B2// has_fallback_type 1812 ) 1813 { 1814 // Destroy lhs's content... 1815 lhs_.destroy_content(); // nothrow 1816 1817 // ...copy rhs content into lhs's storage... 1818 new(lhs_.storage_.address()) 1819 RhsT( rhs_content ); // nothrow 1820 1821 // ...and indicate new content type: 1822 lhs_.indicate_which(rhs_which_); // nothrow 1823 } 1824 1825 template <typename RhsT, typename B> 1826 void assign_impl( 1827 RhsT& rhs_content 1828 , mpl::true_// has_nothrow_copy 1829 , mpl::true_// has_nothrow_move_constructor 1830 , B// has_fallback_type 1831 ) 1832 { 1833 // ...destroy lhs's content... 1834 lhs_.destroy_content(); // nothrow 1835 1836 // ...move the rhs_content into lhs's storage... 1837 new(lhs_.storage_.address()) 1838 RhsT( detail::variant::move(rhs_content) ); // nothrow 1839 1840 // ...and indicate new content type: 1841 lhs_.indicate_which(rhs_which_); // nothrow 1842 } 1843 1844 template <typename RhsT> 1845 void assign_impl( 1846 RhsT& rhs_content 1847 , mpl::false_// has_nothrow_copy 1848 , mpl::false_// has_nothrow_move_constructor 1849 , mpl::true_// has_fallback_type 1850 ) 1851 { 1852 // Destroy lhs's content... 1853 lhs_.destroy_content(); // nothrow 1854 1855 try 1856 { 1857 // ...and attempt to copy rhs's content into lhs's storage: 1858 new(lhs_.storage_.address()) 1859 RhsT( detail::variant::move(rhs_content) ); 1860 } 1861 catch (...) 1862 { 1863 // In case of failure, default-construct fallback type in lhs's storage... 1864 new (lhs_.storage_.address()) 1865 fallback_type_; // nothrow 1866 1867 // ...indicate construction of fallback type... 1868 lhs_.indicate_which( 1869 BOOST_MPL_AUX_VALUE_WKND(fallback_type_index_)::value 1870 ); // nothrow 1871 1872 // ...and rethrow: 1873 throw; 1874 } 1875 1876 // In the event of success, indicate new content type: 1877 lhs_.indicate_which(rhs_which_); // nothrow 1878 } 1879 1880 template <typename RhsT> 1881 void assign_impl( 1882 const RhsT& rhs_content 1883 , mpl::false_// has_nothrow_copy 1884 , mpl::false_// has_nothrow_move_constructor 1885 , mpl::false_// has_fallback_type 1886 ) 1887 { 1888 detail::variant::backup_assigner<wknd_self_t> 1889 visitor(lhs_, rhs_which_, rhs_content); 1890 lhs_.internal_apply_visitor(visitor); 1891 } 1892 1893 public: // internal visitor interfaces 1894 1895 template <typename RhsT> 1896 BOOST_VARIANT_AUX_RETURN_VOID_TYPE 1897 internal_visit(RhsT& rhs_content, int) 1898 { 1899 typedef typename detail::variant::has_nothrow_move_constructor<RhsT>::type 1900 nothrow_move_constructor; 1901 typedef typename mpl::or_< // reduces compile-time 1902 nothrow_move_constructor 1903 , has_nothrow_copy<RhsT> 1904 >::type nothrow_copy; 1905 1906 assign_impl( 1907 rhs_content 1908 , nothrow_copy() 1909 , nothrow_move_constructor() 1910 , has_fallback_type_() 1911 ); 1912 1913 BOOST_VARIANT_AUX_RETURN_VOID; 1914 } 1915 1916 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600)) 1917 private: 1918 // silence MSVC warning C4512: assignment operator could not be generated 1919 move_assigner& operator= (move_assigner const&); 1920 #endif 1921 }; 1922 1923 friend class move_assigner; 1924 #endif // BOOST_NO_RVALUE_REFERENCES 1925 1611 1926 void variant_assign(const variant& rhs) 1612 1927 { 1613 1928 // If the contained types are EXACTLY the same... … … 1625 1940 } 1626 1941 } 1627 1942 1943 #ifndef BOOST_NO_RVALUE_REFERENCES 1944 void variant_assign(variant&& rhs) 1945 { 1946 // If the contained types are EXACTLY the same... 1947 if (which_ == rhs.which_) 1948 { 1949 // ...then move rhs's storage to lhs's content: 1950 detail::variant::move_storage visitor(rhs.storage_.address()); 1951 this->internal_apply_visitor(visitor); 1952 } 1953 else 1954 { 1955 // Otherwise, perform general (move-based) variant assignment: 1956 move_assigner visitor(*this, rhs.which()); 1957 rhs.internal_apply_visitor(visitor); 1958 } 1959 } 1960 #endif // BOOST_NO_RVALUE_REFERENCES 1961 1628 1962 private: // helpers, for modifiers (below) 1629 1963 1630 1964 template <typename T> … … 1645 1979 } 1646 1980 } 1647 1981 1982 #ifndef BOOST_NO_RVALUE_REFERENCES 1983 template <typename T> 1984 void move_assign(T&& rhs) 1985 { 1986 // If direct T-to-T move assignment is not possible... 1987 detail::variant::direct_mover<T> direct_move(rhs); 1988 if (this->apply_visitor(direct_move) == false) 1989 { 1990 // ...then convert rhs to variant and assign: 1991 // 1992 // While potentially inefficient, the following construction of a 1993 // variant allows T as any type convertible to one of the bounded 1994 // types without excessive code redundancy. 1995 // 1996 variant temp( detail::variant::move(rhs) ); 1997 variant_assign( detail::variant::move(temp) ); 1998 } 1999 } 2000 #endif // BOOST_NO_RVALUE_REFERENCES 2001 1648 2002 public: // modifiers 1649 2003 2004 #ifndef BOOST_NO_RVALUE_REFERENCES 2005 template <class T> 2006 typename boost::enable_if<boost::is_rvalue_reference<T&&>, variant& >::type operator=(T&& rhs) 2007 { 2008 move_assign( detail::variant::move(rhs) ); 2009 return *this; 2010 } 2011 #endif // BOOST_NO_RVALUE_REFERENCES 2012 1650 2013 template <typename T> 1651 2014 variant& operator=(const T& rhs) 1652 2015 { … … 1661 2024 return *this; 1662 2025 } 1663 2026 2027 #ifndef BOOST_NO_RVALUE_REFERENCES 2028 variant& operator=(variant&& rhs) 2029 { 2030 variant_assign( detail::variant::move(rhs) ); 2031 return *this; 2032 } 2033 #endif // BOOST_NO_RVALUE_REFERENCES 2034 1664 2035 void swap(variant& rhs) 1665 2036 { 1666 2037 // If the contained types are the same... … … 1685 2056 // NOTE: member which() defined above. 1686 2057 // 1687 2058 1688 bool empty() const 2059 bool empty() const BOOST_NOEXCEPT 1689 2060 { 1690 2061 return false; 1691 2062 }