////////////////////////////////////////////////////////////////////////////// // // (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 #ifndef BOOST_CONFIG_HPP # include #endif # #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 //for std::size_t #include //forceinline //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 lslboost::move #if !defined(BOOST_MOVE_DOXYGEN_INVOKED) #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) namespace lslboost_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 lslboost_move_member_swap namespace lslboost_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 BOOST_MOVE_FORCEINLINE void swap_proxy(T& x, T& y, typename lslboost::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 BOOST_MOVE_FORCEINLINE void swap_proxy(T& x, T& y , typename lslboost::move_detail::enable_if< and_op_not_impl , lslboost_move_member_swap::has_member_swap > >::type* = 0) { T t(::lslboost::move(x)); x = ::lslboost::move(y); y = ::lslboost::move(t); } template BOOST_MOVE_FORCEINLINE void swap_proxy(T& x, T& y , typename lslboost::move_detail::enable_if< and_op_impl< lslboost::move_detail::has_move_emulation_enabled_impl , lslboost_move_member_swap::has_member_swap > >::type* = 0) { x.swap(y); } } //namespace lslboost_move_adl_swap{ #else namespace lslboost_move_adl_swap{ template BOOST_MOVE_FORCEINLINE void swap_proxy(T& x, T& y) { using std::swap; swap(x, y); } } //namespace lslboost_move_adl_swap{ #endif //#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) namespace lslboost_move_adl_swap{ template void swap_proxy(T (& x)[N], T (& y)[N]) { for (std::size_t i = 0; i < N; ++i){ ::lslboost_move_adl_swap::swap_proxy(x[i], y[i]); } } } //namespace lslboost_move_adl_swap { #endif //!defined(BOOST_MOVE_DOXYGEN_INVOKED) namespace lslboost{ //! 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(::lslboost::move(x)); x = ::lslboost::move(y); y = ::lslboost::move(t);. template BOOST_MOVE_FORCEINLINE void adl_move_swap(T& x, T& y) { ::lslboost_move_adl_swap::swap_proxy(x, y); } //! Exchanges elements between range [first1, last1) and another range starting at first2 //! using lslboost::adl_move_swap. //! //! Parameters: //! first1, last1 - the first range of elements to swap //! first2 - beginning of the second range of elements to swap //! //! Type requirements: //! - ForwardIt1, ForwardIt2 must meet the requirements of ForwardIterator. //! - The types of dereferenced ForwardIt1 and ForwardIt2 must meet the //! requirements of Swappable //! //! Return value: Iterator to the element past the last element exchanged in the range //! beginning with first2. template ForwardIt2 adl_move_swap_ranges(ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2) { while (first1 != last1) { ::lslboost::adl_move_swap(*first1, *first2); ++first1; ++first2; } return first2; } template BidirIt2 adl_move_swap_ranges_backward(BidirIt1 first1, BidirIt1 last1, BidirIt2 last2) { while (first1 != last1) { ::lslboost::adl_move_swap(*(--last1), *(--last2)); } return last2; } template void adl_move_iter_swap(ForwardIt1 a, ForwardIt2 b) { lslboost::adl_move_swap(*a, *b); } } //namespace lslboost{ #endif //#ifndef BOOST_MOVE_ADL_MOVE_SWAP_HPP