/*============================================================================= Copyright (c) 2011-2019 Bolero MURAKAMI https://github.com/bolero-MURAKAMI/Sprout 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) =============================================================================*/ #ifndef SPROUT_FUNCTIONAL_EQUIV_HPP #define SPROUT_FUNCTIONAL_EQUIV_HPP #include #include #include #include #include #include namespace sprout { namespace detail { template::value> class equiv_adaptor_impl; template class equiv_adaptor_impl { public: typedef typename Compare::first_argument_type first_argument_type; typedef typename Compare::second_argument_type second_argument_type; typedef bool result_type; protected: Compare fn; public: explicit SPROUT_CONSTEXPR equiv_adaptor_impl(Compare const& comp) : fn(comp) {} SPROUT_CONSTEXPR bool operator()(typename Compare::first_argument_type const& x, typename Compare::second_argument_type const& y) const { return !fn(x, y) && !fn(y, x); } }; template class equiv_adaptor_impl { protected: Compare fn; public: explicit SPROUT_CONSTEXPR equiv_adaptor_impl(Compare const& comp) : fn(comp) {} template SPROUT_CONSTEXPR decltype(!std::declval()(std::declval(), std::declval()) && !std::declval()(std::declval(), std::declval())) operator()(T&& x, U&& y) const { return !fn(SPROUT_FORWARD(T, x), SPROUT_FORWARD(U, y)) && !fn(SPROUT_FORWARD(U, y), SPROUT_FORWARD(T, x)); } }; } // namespace detail // // equiv_adaptor // template class equiv_adaptor : public sprout::detail::equiv_adaptor_impl { public: explicit SPROUT_CONSTEXPR equiv_adaptor(Compare const& comp) : sprout::detail::equiv_adaptor_impl(comp) {} }; template<> class equiv_adaptor : public sprout::detail::equiv_adaptor_impl > { public: SPROUT_CONSTEXPR equiv_adaptor() : sprout::detail::equiv_adaptor_impl >(sprout::less<>()) {} explicit SPROUT_CONSTEXPR equiv_adaptor(sprout::less<> const& comp) : sprout::detail::equiv_adaptor_impl >(comp) {} }; // // equiv // template inline SPROUT_CONSTEXPR sprout::equiv_adaptor equiv(Compare const& comp) { return sprout::equiv_adaptor(comp); } inline SPROUT_CONSTEXPR sprout::equiv_adaptor<> equiv() { return sprout::equiv_adaptor<>(); } } // namespace sprout #endif // #ifndef SPROUT_FUNCTIONAL_EQUIV_HPP