Header file range/v3/utility/swap.hpp

#include <meta/meta.hpp>

#include <range/v3/range_fwd.hpp>

#include <range/v3/utility/move.hpp>

#include <range/v3/utility/associated_types.hpp>

#include <range/v3/utility/static_const.hpp>

namespace ranges
{
    inline namespace v3
    {
        namespace adl_swap_detail
        {
            using std::swap;
            
            template <typename First0, typename Second0, typename First1, typename Second1>
            constexpr meta::if_c<is_swappable<First0, First1>::value&&is_swappable<Second0, Second1>::value> swap(std::pair<First0, Second0>&& left, std::pair<First1, Second1>&& right) noexcept(is_nothrow_swappable<First0, First1>::value&&is_nothrow_swappable<Second0, Second1>::value);
            
            template <typename ... Ts, typename ... Us>
            constexpr meta::if_c<meta::and_c<is_swappable<Ts, Us>::value...>::value> swap(std::tuple<Ts...>&& left, std::tuple<Us...>&& right) noexcept(meta::and_c<is_nothrow_swappable<Ts, Us>::value...>::value);
            
            struct swap_fn
            {
                template <typename T, typename U>
                constexpr meta::if_c<is_swappable<T, U>::value> operator()(T&& t, U&& u) const noexcept(is_nothrow_swappable<T, U>::value);
            };
            
            template <typename T, typename U, typename Enable = void>
            struct is_swappable_
            : std::false_type
            {};
            
            template <typename T, typename U>
            struct is_swappable_<T, U, meta::void_<decltype(swap(std::declval<T>(), std::declval<U>())), decltype(swap(std::declval<U>(), std::declval<T>()))>>
            : std::true_type
            {};
            
            template <typename T, typename U>
            struct is_nothrow_swappable_
            : meta::bool_<noexcept(swap(std::declval<T>(), std::declval<U>()))>
            {};
            
            template <typename ... Ts, typename ... Us, std::size_t ... Is>
            constexpr void tuple_swap_(std::tuple<Ts...>&& left, std::tuple<Us...>&& right, meta::index_sequence<Is...>);
            
            template <typename Readable0, typename Readable1>
            constexpr meta::if_c<is_swappable<decltype(*std::declval<Readable0&>()), decltype(*std::declval<Readable1&>())>::value> indirect_swap(Readable0 a, Readable1 b) noexcept(is_nothrow_swappable<decltype(*std::declval<Readable0&>()), decltype(*std::declval<Readable1&>())>::value);
            
            template <typename Readable0, typename Readable1>
            constexpr meta::if_c<!is_swappable<decltype(*std::declval<Readable0&>()), decltype(*std::declval<Readable1&>())>::value&&is_indirectly_movable<Readable0, Readable1>::value&&is_indirectly_movable<Readable1, Readable0>::value> indirect_swap(Readable0 a, Readable1 b) noexcept(is_nothrow_indirectly_movable<Readable0, Readable1>::value&&is_nothrow_indirectly_movable<Readable1, Readable0>::value);
            
            struct indirect_swap_fn
            {
                template <typename Readable0, typename Readable1>
                constexpr meta::if_c<is_indirectly_swappable<Readable0, Readable1>::value> operator()(Readable0 a, Readable1 b) const noexcept(is_nothrow_indirectly_swappable<Readable0, Readable1>::value);
            };
            
            template <typename T, typename U, typename Enable = void>
            struct is_indirectly_swappable_
            : std::false_type
            {};
            
            template <typename T, typename U>
            struct is_indirectly_swappable_<T, U, meta::void_<decltype(indirect_swap(std::declval<T>(), std::declval<U>()))>>
            : std::true_type
            {};
            
            template <typename T, typename U>
            struct is_nothrow_indirectly_swappable_
            : meta::bool_<noexcept(indirect_swap(std::declval<T>(), std::declval<U>()))>
            {};
        }
        
        template <typename T, typename U>
        struct is_swappable;
        
        template <typename T, typename U>
        struct is_nothrow_swappable;
        
        template <typename T, typename U>
        struct is_indirectly_swappable;
        
        template <typename T, typename U>
        struct is_nothrow_indirectly_swappable;
        
        inline namespace 
        {
            constexpr auto& swap = static_const<adl_swap_detail::swap_fn>::value;
        }
        
        inline namespace 
        {
            constexpr auto& indirect_swap = static_const<adl_swap_detail::indirect_swap_fn>::value;
        }
    }
}