williamr@2: //----------------------------------------------------------------------------- williamr@2: // boost variant/detail/move.hpp header file williamr@2: // See http://www.boost.org for updates, documentation, and revision history. williamr@2: //----------------------------------------------------------------------------- williamr@2: // williamr@2: // Copyright (c) 2002-2003 Eric Friedman williamr@2: // Copyright (c) 2002 by Andrei Alexandrescu williamr@2: // williamr@2: // Use, modification and distribution are subject to the williamr@2: // Boost Software License, Version 1.0. (See accompanying file williamr@2: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) williamr@2: // williamr@2: // This file derivative of MoJO. Much thanks to Andrei for his initial work. williamr@2: // See for information on MOJO. williamr@2: // Re-issued here under the Boost Software License, with permission of the original williamr@2: // author (Andrei Alexandrescu). williamr@2: williamr@2: williamr@2: #ifndef BOOST_VARIANT_DETAIL_MOVE_HPP williamr@2: #define BOOST_VARIANT_DETAIL_MOVE_HPP williamr@2: williamr@2: #include // for iterator_traits williamr@2: #include // for placement new williamr@2: williamr@2: #include "boost/config.hpp" williamr@2: #include "boost/detail/workaround.hpp" williamr@2: #include "boost/mpl/if.hpp" williamr@2: #include "boost/type_traits/is_base_and_derived.hpp" williamr@2: williamr@2: namespace boost { williamr@2: namespace detail { namespace variant { williamr@2: williamr@2: ////////////////////////////////////////////////////////////////////////// williamr@2: // forward declares williamr@2: // williamr@2: // NOTE: Incomplete until (if?) Boost.Move becomes part of Boost. williamr@2: // williamr@2: template class moveable; williamr@2: template class move_source; williamr@2: template class move_return; williamr@2: williamr@2: namespace detail { williamr@2: williamr@2: // (detail) moveable_tag williamr@2: // williamr@2: // Concrete type from which moveable derives. williamr@2: // williamr@2: // TODO: Move into moveable_fwd.hpp and define has_move_constructor. williamr@2: // williamr@2: template williamr@2: struct moveable_tag williamr@2: { williamr@2: }; williamr@2: williamr@2: } // namespace detail williamr@2: williamr@2: ////////////////////////////////////////////////////////////////////////// williamr@2: // function template move williamr@2: // williamr@2: // Takes a T& and returns, if T derives moveable, a move_source for williamr@2: // the object; else, returns the T&. williamr@2: // williamr@2: williamr@2: namespace detail { williamr@2: williamr@2: // (detail) class template move_type williamr@2: // williamr@2: // Metafunction that, given moveable T, provides move_source, else T&. williamr@2: // williamr@2: template williamr@2: struct move_type williamr@2: { williamr@2: public: // metafunction result williamr@2: williamr@2: typedef typename mpl::if_< williamr@2: is_base_and_derived, T> williamr@2: , move_source williamr@2: , T& williamr@2: >::type type; williamr@2: williamr@2: }; williamr@2: williamr@2: } // namespace detail williamr@2: williamr@2: template williamr@2: inline williamr@2: typename detail::move_type::type williamr@2: move(T& source) williamr@2: { williamr@2: typedef typename detail::move_type::type williamr@2: move_t; williamr@2: williamr@2: return move_t(source); williamr@2: } williamr@2: williamr@2: ////////////////////////////////////////////////////////////////////////// williamr@2: // class template return_t williamr@2: // williamr@2: // Metafunction that, given moveable T, provides move_return, else T. williamr@2: // williamr@2: template williamr@2: struct return_t williamr@2: { williamr@2: public: // metafunction result williamr@2: williamr@2: typedef typename mpl::if_< williamr@2: is_base_and_derived, T> williamr@2: , move_return williamr@2: , T williamr@2: >::type type; williamr@2: williamr@2: }; williamr@2: williamr@2: ////////////////////////////////////////////////////////////////////////// williamr@2: // function template move_swap williamr@2: // williamr@2: // Swaps using Koenig lookup but falls back to move-swap for primitive williamr@2: // types and on non-conforming compilers. williamr@2: // williamr@2: williamr@2: #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) \ williamr@2: || BOOST_WORKAROUND(__GNUC__, BOOST_TESTED_AT(2)) williamr@2: williamr@2: // [Indicate that move_swap by overload is disabled...] williamr@2: #define BOOST_NO_MOVE_SWAP_BY_OVERLOAD williamr@2: williamr@2: // [...and provide straight swap-by-move implementation:] williamr@2: template williamr@2: inline void move_swap(T& lhs, T& rhs) williamr@2: { williamr@2: T tmp( boost::detail::variant::move(lhs) ); williamr@2: lhs = boost::detail::variant::move(rhs); williamr@2: rhs = boost::detail::variant::move(tmp); williamr@2: } williamr@2: williamr@2: #else// !workaround williamr@2: williamr@2: namespace detail { namespace move_swap { williamr@2: williamr@2: template williamr@2: inline void swap(T& lhs, T& rhs) williamr@2: { williamr@2: T tmp( boost::detail::variant::move(lhs) ); williamr@2: lhs = boost::detail::variant::move(rhs); williamr@2: rhs = boost::detail::variant::move(tmp); williamr@2: } williamr@2: williamr@2: }} // namespace detail::move_swap williamr@2: williamr@2: template williamr@2: inline void move_swap(T& lhs, T& rhs) williamr@2: { williamr@2: using detail::move_swap::swap; williamr@2: williamr@2: swap(lhs, rhs); williamr@2: } williamr@2: williamr@2: #endif // workaround williamr@2: williamr@2: }} // namespace detail::variant williamr@2: } // namespace boost williamr@2: williamr@2: #endif // BOOST_VARIANT_DETAIL_MOVE_HPP williamr@2: williamr@2: williamr@2: