summaryrefslogtreecommitdiff
path: root/boost/move/adl_move_swap.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/move/adl_move_swap.hpp')
-rw-r--r--boost/move/adl_move_swap.hpp233
1 files changed, 233 insertions, 0 deletions
diff --git a/boost/move/adl_move_swap.hpp b/boost/move/adl_move_swap.hpp
new file mode 100644
index 0000000000..2a010cda57
--- /dev/null
+++ b/boost/move/adl_move_swap.hpp
@@ -0,0 +1,233 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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 <boost/config.hpp>
+#include <cstddef> //for std::size_t
+
+//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>
+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>
+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>
+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>
+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