From cbda10ecdde552655a664cdbbd9af9e7ea55b1c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Wed, 26 Nov 2014 19:27:40 +0100 Subject: [PATCH] Added adl_move_swap utility --- include/boost/move/adl_move_swap.hpp | 89 ++++++++++++++++++++++++++++ include/boost/move/unique_ptr.hpp | 6 +- include/boost/move/utility_core.hpp | 8 --- proj/vc7ide/Move.sln | 1 + test/unique_ptr_modifiers.cpp | 3 +- 5 files changed, 95 insertions(+), 12 deletions(-) create mode 100644 include/boost/move/adl_move_swap.hpp diff --git a/include/boost/move/adl_move_swap.hpp b/include/boost/move/adl_move_swap.hpp new file mode 100644 index 0000000..c2c92dc --- /dev/null +++ b/include/boost/move/adl_move_swap.hpp @@ -0,0 +1,89 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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(_MSC_VER) +# 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) + #if (__GNUC__ < 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ < 3)) + #include //algobase is lighter than + #elif ((__GNUC__ == 4) && (__GNUC_MINOR__ == 3)) + //In GCC 4.3 a tiny stl_move.h was created with swap and move utilities + #include //algobase is much lighter than + #else + //In GCC 4.4 stl_move.h was renamed to move.h + #include //algobase is much lighter than + #endif +#elif defined(_LIBCPP_VERSION) + #include //The initial import of libc++ defines std::swap and still there +#else //Fallback + #include +#endif + +#include //for boost::move + +namespace boost_move_adl_swap{ + +template +void swap_proxy(T& left, T& right, 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(left, right); +} + +template +void swap_proxy(T& left, T& right, typename boost::move_detail::enable_if_c::value>::type* = 0) +{ + T tmp(::boost::move(left)); + left = ::boost::move(right); + right = ::boost::move(tmp); +} + +template +void swap_proxy(T (& left)[N], T (& right)[N]) +{ + for (std::size_t i = 0; i < N; ++i){ + ::boost_move_adl_swap::swap_proxy(left[i], right[i]); + } +} + +} //namespace boost_move_adl_swap { + +namespace boost{ + +// adl_move_swap has two template arguments, instead of one, to +// avoid ambiguity when swapping objects of a Boost type that does +// not have its own boost::swap overload. +template +void adl_move_swap(T& left, T& right) +{ + ::boost_move_adl_swap::swap_proxy(left, right); +} + +} //namespace boost{ + +#endif //#ifndef BOOST_MOVE_ADL_MOVE_SWAP_HPP diff --git a/include/boost/move/unique_ptr.hpp b/include/boost/move/unique_ptr.hpp index 231735b..48fa275 100644 --- a/include/boost/move/unique_ptr.hpp +++ b/include/boost/move/unique_ptr.hpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -727,9 +728,8 @@ class unique_ptr //! Effects: Invokes swap on the stored pointers and on the stored deleters of *this and u. void swap(unique_ptr& u) BOOST_NOEXCEPT { - using ::boost::move_detail::swap; - swap(m_data.m_p, u.m_data.m_p); - swap(m_data.deleter(), u.m_data.deleter()); + ::boost::adl_move_swap(m_data.m_p, u.m_data.m_p); + ::boost::adl_move_swap(m_data.deleter(), u.m_data.deleter()); } }; diff --git a/include/boost/move/utility_core.hpp b/include/boost/move/utility_core.hpp index 30ab539..8d09e2a 100644 --- a/include/boost/move/utility_core.hpp +++ b/include/boost/move/utility_core.hpp @@ -277,14 +277,6 @@ namespace boost{ namespace move_detail{ -template -void swap(T &a, T &b) -{ - T c((::boost::move(a))); - a = ::boost::move(b); - b = ::boost::move(c); -} - template typename boost::move_detail::add_rvalue_reference::type declval(); diff --git a/proj/vc7ide/Move.sln b/proj/vc7ide/Move.sln index c12681b..bb3bfb9 100644 --- a/proj/vc7ide/Move.sln +++ b/proj/vc7ide/Move.sln @@ -217,6 +217,7 @@ Global {C57C28A3-4FE0-6208-BF87-B2B61D3A7675}.Release.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionItems) = postSolution + ..\..\..\..\boost\move\adl_move_swap.hpp = ..\..\..\..\boost\move\adl_move_swap.hpp ..\..\..\..\boost\move\algorithm.hpp = ..\..\..\..\boost\move\algorithm.hpp ..\..\..\..\boost\move\detail\config_begin.hpp = ..\..\..\..\boost\move\detail\config_begin.hpp ..\..\..\..\boost\move\detail\config_end.hpp = ..\..\..\..\boost\move\detail\config_end.hpp diff --git a/test/unique_ptr_modifiers.cpp b/test/unique_ptr_modifiers.cpp index b67d4f5..3de952d 100644 --- a/test/unique_ptr_modifiers.cpp +++ b/test/unique_ptr_modifiers.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include ////////////////////////////////////////////// @@ -284,7 +285,7 @@ void test() BOOST_TEST(s2.get() == p2); BOOST_TEST(*s2 == A(2)); BOOST_TEST(s2.get_deleter().state() == 2); - swap(s1, s2); + boost::adl_move_swap(s1, s2); BOOST_TEST(s1.get() == p2); BOOST_TEST(*s1 == A(2)); BOOST_TEST(s1.get_deleter().state() == 2);