Ticket #7718: rvalues2.patch

File rvalues2.patch, 8.8 KB (added by Antony Polukhin, 10 years ago)
  • detail/initializer.hpp

     
    2020#include "boost/call_traits.hpp"
    2121#include "boost/detail/reference_content.hpp"
    2222#include "boost/variant/recursive_wrapper_fwd.hpp"
     23#include "boost/variant/detail/move.hpp"
    2324
    2425#if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
    2526#   include "boost/mpl/aux_/value_wknd.hpp"
     
    7980                recursive_enabled_T;
    8081            typedef typename unwrap_recursive<recursive_enabled_T>::type
    8182                public_T;
     83
     84#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
     85            typedef boost::is_reference<public_T>
     86                is_reference_content_t;
     87
     88            typedef typename boost::mpl::if_<is_reference_content_t, public_T, const public_T& >::type
     89                param_T;
     90
     91            template <class T> struct disable_overload{};
     92
     93            typedef typename boost::mpl::if_<is_reference_content_t, disable_overload<public_T>, public_T&& >::type
     94                param2_T;
     95#else
    8296            typedef typename call_traits<public_T>::param_type
    8397                param_T;
     98#endif
    8499
    85100        public: // static functions
    86101
     
    96111                return BOOST_MPL_AUX_VALUE_WKND(index)::value; // which
    97112            }
    98113
     114#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
     115            static int initialize(void* dest, param2_T operand)
     116            {
     117                // This assert must newer trigger, because all the reference contents are
     118                // handled by the initilize(void* dest, param_T operand) function above
     119                BOOST_ASSERT(!is_reference_content_t::value);
     120
     121                typedef typename boost::mpl::if_<is_reference_content_t, param2_T, public_T>::type value_T;
     122                new(dest) value_T( boost::detail::variant::move(operand) );
     123                return BOOST_MPL_AUX_VALUE_WKND(index)::value; // which
     124            }
     125#endif
    99126        };
    100127
    101128        friend class initializer_node;
  • detail/backup_holder.hpp

     
    1313#ifndef BOOST_VARIANT_DETAIL_BACKUP_HOLDER_HPP
    1414#define BOOST_VARIANT_DETAIL_BACKUP_HOLDER_HPP
    1515
    16 #include "boost/config.hpp"
    1716#include "boost/assert.hpp"
    1817
    1918namespace boost {
     
    3332        delete backup_;
    3433    }
    3534
    36     explicit backup_holder(T* backup) BOOST_NOEXCEPT
     35    explicit backup_holder(T* backup)
    3736        : backup_(backup)
    3837    {
    3938    }
     
    5453        return *this;
    5554    }
    5655
    57     void swap(backup_holder& rhs) BOOST_NOEXCEPT
     56    void swap(backup_holder& rhs)
    5857    {
    5958        T* tmp = rhs.backup_;
    6059        rhs.backup_ = this->backup_;
     
    8483}
    8584
    8685template <typename T>
    87 void swap(backup_holder<T>& lhs, backup_holder<T>& rhs) BOOST_NOEXCEPT
     86void swap(backup_holder<T>& lhs, backup_holder<T>& rhs)
    8887{
    8988    lhs.swap(rhs);
    9089}
  • variant.hpp

     
    14681468
    14691469    friend class convert_copy_into;
    14701470
     1471#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
     1472    class convert_move_into
     1473        : public static_visitor<int>
     1474    {
     1475    private: // representation
     1476
     1477        void* storage_;
     1478
     1479    public: // structors
     1480
     1481        explicit convert_move_into(void* storage) BOOST_NOEXCEPT
     1482            : storage_(storage)
     1483        {
     1484        }
     1485
     1486    public: // internal visitor interfaces (below)
     1487
     1488        template <typename T>
     1489        int internal_visit(T& operand, int) const
     1490        {
     1491            // NOTE TO USER :
     1492            // Compile error here indicates one of the source variant's types
     1493            // cannot be unambiguously converted to the destination variant's
     1494            // types (or that no conversion exists).
     1495            //
     1496            return initializer::initialize(storage_, detail::variant::move(operand) );
     1497        }
     1498
     1499        template <typename T>
     1500        int internal_visit(boost::detail::reference_content<T>& operand, long) const
     1501        {
     1502            return internal_visit( operand.get(), 1L );
     1503        }
     1504
     1505        template <typename T>
     1506        int internal_visit(const boost::detail::reference_content<T>& operand, long) const
     1507        {
     1508            return internal_visit( operand.get(), 1L );
     1509        }
     1510
     1511        template <typename T>
     1512        int internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
     1513        {
     1514            return internal_visit( operand.get(), 1L );
     1515        }
     1516
     1517        template <typename T>
     1518        int internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
     1519        {
     1520            return internal_visit( operand.get(), 1L );
     1521        }
     1522
     1523        template <typename T>
     1524        int internal_visit(boost::recursive_wrapper<T>& operand, long) const
     1525        {
     1526            return internal_visit( operand.get(), 1L );
     1527        }
     1528
     1529        template <typename T>
     1530        int internal_visit(const boost::recursive_wrapper<T>& operand, long) const
     1531        {
     1532            return internal_visit( operand.get(), 1L );
     1533        }
     1534    };
     1535
     1536    friend class convert_move_into;
     1537#endif
     1538
    14711539private: // helpers, for structors, below
    14721540
    14731541    template <typename T>
     
    14901558            );
    14911559    }
    14921560
     1561#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
     1562    template <typename T>
     1563    typename boost::enable_if<boost::is_rvalue_reference<T&&> >::type convert_construct(
     1564          T&& operand
     1565        , int
     1566        , mpl::false_ = mpl::false_() // is_foreign_variant
     1567        )
     1568    {
     1569        // NOTE TO USER :
     1570        // Compile error here indicates that the given type is not
     1571        // unambiguously convertible to one of the variant's types
     1572        // (or that no conversion exists).
     1573        //
     1574        indicate_which(
     1575              initializer::initialize(
     1576                  storage_.address()
     1577                , detail::variant::move(operand)
     1578                )
     1579            );
     1580    }
     1581#endif
     1582
    14931583    template <typename Variant>
    14941584    void convert_construct(
    14951585          Variant& operand
     
    15031593            );
    15041594    }
    15051595
     1596#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
    15061597    template <typename Variant>
     1598    typename boost::enable_if<boost::is_rvalue_reference<Variant&&> >::type convert_construct(
     1599          Variant&& operand
     1600        , long
     1601        , mpl::true_// is_foreign_variant
     1602        )
     1603    {
     1604        convert_move_into visitor(storage_.address());
     1605        indicate_which(
     1606              operand.internal_apply_visitor(visitor)
     1607            );
     1608    }
     1609#endif
     1610
     1611    template <typename Variant>
    15071612    void convert_construct_variant(Variant& operand)
    15081613    {
    15091614        // [Determine if the given variant is itself a bounded type, or if its
     
    15301635            );
    15311636    }
    15321637
     1638#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
     1639    template <typename Variant>
     1640    typename boost::enable_if<boost::is_rvalue_reference<Variant&&> >::type convert_construct_variant(Variant&& operand)
     1641    {
     1642        // [Determine if the given variant is itself a bounded type, or if its
     1643        //  content needs to be converted (i.e., it is a 'foreign' variant):]
     1644        //
     1645
     1646        typedef typename mpl::find_if<
     1647              types
     1648            , is_same<
     1649                  add_const<mpl::_1>
     1650                , const Variant
     1651                >
     1652            >::type found_it;
     1653
     1654        typedef typename mpl::end<types>::type not_found;
     1655        typedef typename is_same<
     1656              found_it, not_found
     1657            >::type is_foreign_variant;
     1658
     1659        // Convert move construct from operand:
     1660        convert_construct(
     1661              detail::variant::move(operand), 1L
     1662            , is_foreign_variant()
     1663            );
     1664    }
     1665#endif
     1666
    15331667    template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
    15341668    void convert_construct(
    15351669          boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
     
    15481682        convert_construct_variant(operand);   
    15491683    }
    15501684
     1685#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
     1686    template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
     1687    void convert_construct(
     1688          boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>&& operand
     1689        , long
     1690        )
     1691    {
     1692        convert_construct_variant( detail::variant::move(operand) );   
     1693    }
     1694#endif
     1695
    15511696public: // structors, cont.
    15521697
    15531698#if !defined(BOOST_VARIANT_AUX_BROKEN_CONSTRUCTOR_TEMPLATE_ORDERING)
     
    15971742    {
    15981743        convert_construct(operand, 1L);
    15991744    }
    1600 
    16011745#endif // BOOST_VARIANT_AUX_BROKEN_CONSTRUCTOR_TEMPLATE_ORDERING workarounds
     1746   
     1747#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
     1748    template <class T>
     1749    variant(T&& operand, typename boost::enable_if<boost::is_rvalue_reference<T&&> >::type* = 0)
     1750    {
     1751        convert_construct( detail::variant::move(operand), 1L);
     1752    }
     1753#endif
    16021754
    16031755public: // structors, cont.
    16041756