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