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