관리-도구
편집 파일: adl_move_swap.hpp
////////////////////////////////////////////////////////////////////////////// // // (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 <boost/config.hpp> #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 <cstddef> //for std::size_t #include <boost/move/detail/workaround.hpp> //forceinline //Try to avoid including <algorithm>, as it's quite big #if defined(_MSC_VER) && defined(BOOST_DINKUMWARE_STDLIB) #include <utility> //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 <bits/stl_algobase.h> #elif (__GNUC__ == 4) && (__GNUC_MINOR__ == 3) //In GCC 4.3 a tiny stl_move.h was created with swap and move utilities #include <bits/stl_move.h> #else //In GCC 4.4 stl_move.h was renamed to move.h #include <bits/move.h> #endif #elif defined(_LIBCPP_VERSION) #include <type_traits> //The initial import of libc++ defines std::swap and still there #elif __cplusplus >= 201103L #include <utility> //Fallback for C++ >= 2011 #else #include <algorithm> //Fallback for C++98/03 #endif #include <boost/move/utility_core.hpp> //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<typename T> no_type is_private_type(T const &); yes_type is_private_type(private_type const &); template <typename Type> class has_member_function_named_swap { struct BaseMixin { void swap(); }; struct Base : public Type, public BaseMixin { Base(); }; template <typename T, T t> class Helper{}; template <typename U> static no_type deduce(U*, Helper<void (BaseMixin::*)(), &U::swap>* = 0); static yes_type deduce(...); public: static const bool value = sizeof(yes_type) == sizeof(deduce((Base*)(0))); }; template<typename Fun, bool HasFunc> struct has_member_swap_impl { static const bool value = false; }; template<typename Fun> struct has_member_swap_impl<Fun, true> { 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<typename Fun> struct has_member_swap : public has_member_swap_impl <Fun, has_member_function_named_swap<Fun>::value> {}; } //namespace boost_move_member_swap namespace boost_move_adl_swap{ template<class P1, class P2, bool = P1::value> struct and_op_impl { static const bool value = false; }; template<class P1, class P2> struct and_op_impl<P1, P2, true> { static const bool value = P2::value; }; template<class P1, class P2> struct and_op : and_op_impl<P1, P2> {}; ////// template<class P1, class P2, bool = P1::value> struct and_op_not_impl { static const bool value = false; }; template<class P1, class P2> struct and_op_not_impl<P1, P2, true> { static const bool value = !P2::value; }; template<class P1, class P2> struct and_op_not : and_op_not_impl<P1, P2> {}; template<class T> inline void swap_proxy(T& x, T& y, typename boost::move_detail::enable_if_c<!boost::move_detail::has_move_emulation_enabled_impl<T>::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<class T> void swap_proxy(T& x, T& y , typename boost::move_detail::enable_if< and_op_not_impl<boost::move_detail::has_move_emulation_enabled_impl<T> , boost_move_member_swap::has_member_swap<T> > >::type* = 0) { T t(::boost::move(x)); x = ::boost::move(y); y = ::boost::move(t); } template<class T> inline void swap_proxy(T& x, T& y , typename boost::move_detail::enable_if< and_op_impl< boost::move_detail::has_move_emulation_enabled_impl<T> , boost_move_member_swap::has_member_swap<T> > >::type* = 0) { x.swap(y); } } //namespace boost_move_adl_swap{ #else namespace boost_move_adl_swap{ template<class T> inline 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<class T, std::size_t N> 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. //! //! <b>Exception</b>: If T uses Boost.Move's move emulation and the compiler has //! no rvalue references then: //! //! - If T has a <code>T::swap(T&)</code> member, that member is called. //! - Otherwise a move-based swap is called, equivalent to: //! <code>T t(::boost::move(x)); x = ::boost::move(y); y = ::boost::move(t);</code>. template<class T> inline void adl_move_swap(T& x, T& y) { ::boost_move_adl_swap::swap_proxy(x, y); } //! Exchanges elements between range [first1, last1) and another range starting at first2 //! using boost::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<class ForwardIt1, class ForwardIt2> ForwardIt2 adl_move_swap_ranges(ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2) { while (first1 != last1) { ::boost::adl_move_swap(*first1, *first2); ++first1; ++first2; } return first2; } template<class BidirIt1, class BidirIt2> BidirIt2 adl_move_swap_ranges_backward(BidirIt1 first1, BidirIt1 last1, BidirIt2 last2) { while (first1 != last1) { ::boost::adl_move_swap(*(--last1), *(--last2)); } return last2; } template<class ForwardIt1, class ForwardIt2> void adl_move_iter_swap(ForwardIt1 a, ForwardIt2 b) { boost::adl_move_swap(*a, *b); } } //namespace boost{ #endif //#ifndef BOOST_MOVE_ADL_MOVE_SWAP_HPP