Index: boost/move/adl_move_swap.hpp =================================================================== --- boost/move/adl_move_swap.hpp (revision 0) +++ boost/move/adl_move_swap.hpp (revision 0) @@ -0,0 +1,229 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright 2007, 2008 Steven Watanabe, Joseph Gauterin, Niels Dekker +// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_MOVE_ADL_MOVE_SWAP_HPP +#define BOOST_MOVE_ADL_MOVE_SWAP_HPP + +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +//Based on Boost.Core's swap. +//Many thanks to Steven Watanabe, Joseph Gauterin and Niels Dekker. + +#include +#include //for std::size_t + +//Try to avoid including , as it's quite big +#if defined(_MSC_VER) && defined(BOOST_DINKUMWARE_STDLIB) + #include //Dinkum libraries define std::swap in utility which is lighter than algorithm +#elif defined(BOOST_GNU_STDLIB) + //For non-GCC compilers, where GNUC version is not very reliable, or old GCC versions + //use the good old stl_algobase header, which is quite lightweight + #if !defined(BOOST_GCC) || ((__GNUC__ < 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ < 3))) + #include + #elif (__GNUC__ == 4) && (__GNUC_MINOR__ == 3) + //In GCC 4.3 a tiny stl_move.h was created with swap and move utilities + #include + #else + //In GCC 4.4 stl_move.h was renamed to move.h + #include + #endif +#elif defined(_LIBCPP_VERSION) + #include //The initial import of libc++ defines std::swap and still there +#elif __cplusplus >= 201103L + #include //Fallback for C++ >= 2011 +#else + #include //Fallback for C++98/03 +#endif + +#include //for boost::move + +#if !defined(BOOST_MOVE_DOXYGEN_INVOKED) + +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +namespace boost_move_member_swap { + +struct dont_care +{ + dont_care(...); +}; + +struct private_type +{ + static private_type p; + private_type const &operator,(int) const; +}; + +typedef char yes_type; +struct no_type{ char dummy[2]; }; + +template +no_type is_private_type(T const &); + +yes_type is_private_type(private_type const &); + +template +class has_member_function_named_swap +{ + struct BaseMixin + { + void swap(); + }; + + struct Base : public Type, public BaseMixin { Base(); }; + template class Helper{}; + + template + static no_type deduce(U*, Helper* = 0); + static yes_type deduce(...); + + public: + static const bool value = sizeof(yes_type) == sizeof(deduce((Base*)(0))); +}; + +template +struct has_member_swap_impl +{ + static const bool value = false; +}; + +template +struct has_member_swap_impl +{ + struct FunWrap : Fun + { + FunWrap(); + + using Fun::swap; + private_type swap(dont_care) const; + }; + + static Fun &declval_fun(); + static FunWrap declval_wrap(); + + static bool const value = + sizeof(no_type) == sizeof(is_private_type( (declval_wrap().swap(declval_fun()), 0)) ); +}; + +template +struct has_member_swap : public has_member_swap_impl + ::value> +{}; + +} //namespace boost_move_member_swap + +namespace boost_move_adl_swap{ + +template +struct and_op_impl +{ static const bool value = false; }; + +template +struct and_op_impl +{ static const bool value = P2::value; }; + +template +struct and_op + : and_op_impl +{}; + +////// + +template +struct and_op_not_impl +{ static const bool value = false; }; + +template +struct and_op_not_impl +{ static const bool value = !P2::value; }; + +template +struct and_op_not + : and_op_not_impl +{}; + +template +void swap_proxy(T& x, T& y, typename boost::move_detail::enable_if_c::value>::type* = 0) +{ + //use std::swap if argument dependent lookup fails + //Use using directive ("using namespace xxx;") instead as some older compilers + //don't do ADL with using declarations ("using ns::func;"). + using namespace std; + swap(x, y); +} + +template +void swap_proxy(T& x, T& y + , typename boost::move_detail::enable_if< and_op_not_impl + , boost_move_member_swap::has_member_swap > + >::type* = 0) +{ T t(::boost::move(x)); x = ::boost::move(y); y = ::boost::move(t); } + +template +void swap_proxy(T& x, T& y + , typename boost::move_detail::enable_if< and_op_impl< boost::move_detail::has_move_emulation_enabled_impl + , boost_move_member_swap::has_member_swap > + >::type* = 0) +{ x.swap(y); } + +} //namespace boost_move_adl_swap{ + +#else + +namespace boost_move_adl_swap{ + +template +void swap_proxy(T& x, T& y) +{ + using std::swap; + swap(x, y); +} + +} //namespace boost_move_adl_swap{ + +#endif //#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + +namespace boost_move_adl_swap{ + +template +void swap_proxy(T (& x)[N], T (& y)[N]) +{ + for (std::size_t i = 0; i < N; ++i){ + ::boost_move_adl_swap::swap_proxy(x[i], y[i]); + } +} + +} //namespace boost_move_adl_swap { + +#endif //!defined(BOOST_MOVE_DOXYGEN_INVOKED) + +namespace boost{ + +//! Exchanges the values of a and b, using Argument Dependent Lookup (ADL) to select a +//! specialized swap function if available. If no specialized swap function is available, +//! std::swap is used. +//! +//! Exception: If T uses Boost.Move's move emulation and the compiler has +//! no rvalue references then: +//! +//! - If T has a T::swap(T&) member, that member is called. +//! - Otherwise a move-based swap is called, equivalent to: +//! T t(::boost::move(x)); x = ::boost::move(y); y = ::boost::move(t);. +template +void adl_move_swap(T& x, T& y) +{ + ::boost_move_adl_swap::swap_proxy(x, y); +} + +} //namespace boost{ + +#endif //#ifndef BOOST_MOVE_ADL_MOVE_SWAP_HPP Index: boost/variant/detail/move.hpp =================================================================== --- boost/variant/detail/move.hpp (revision 103708) +++ boost/variant/detail/move.hpp (working copy) @@ -5,7 +5,7 @@ // // Copyright (c) 2002-2003 Eric Friedman // Copyright (c) 2002 by Andrei Alexandrescu -// Copyright (c) 2013 Antony Polukhin +// Copyright (c) 2013-2014 Antony Polukhin // // Use, modification and distribution are subject to the // Boost Software License, Version 1.0. (See accompanying file @@ -26,6 +26,7 @@ #include "boost/config.hpp" #include "boost/detail/workaround.hpp" #include "boost/move/move.hpp" +#include "boost/move/adl_move_swap.hpp" namespace boost { namespace detail { namespace variant { @@ -38,27 +39,10 @@ // types and on non-conforming compilers. // -namespace move_swap_fallback { - -template -inline void swap(T1& lhs, T2& rhs) -{ - T1 tmp( boost::detail::variant::move(lhs) ); - lhs = boost::detail::variant::move(rhs); - rhs = boost::detail::variant::move(tmp); -} - -} // namespace move_swap_fallback - template inline void move_swap(T& lhs, T& rhs) { -#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) - move_swap_fallback::swap(lhs, rhs); -#else - using move_swap_fallback::swap; - swap(lhs, rhs); -#endif + ::boost::adl_move_swap(lhs, rhs); } }}} // namespace boost::detail::variant