/*! @file Defines `boost::hana::equal`. @copyright Louis Dionne 2013-2017 Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) */ #ifndef BOOST_HANA_EQUAL_HPP #define BOOST_HANA_EQUAL_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // required by fwd decl #include #include #include #include #include #include BOOST_HANA_NAMESPACE_BEGIN //! @cond template constexpr auto equal_t::operator()(X&& x, Y&& y) const { using T = typename hana::tag_of::type; using U = typename hana::tag_of::type; using Equal = equal_impl; return Equal::apply(static_cast(x), static_cast(y)); } //! @endcond template struct equal_impl> : default_ { template static constexpr auto apply(X const&, Y const&) { // Delay the static_assert by ensuring T_ is dependent. using T_ = typename hana::tag_of::type; static_assert(!hana::is_convertible::value && !hana::is_convertible::value, "No default implementation of hana::equal is provided for related " "types that can't be safely embedded into a common type, because " "those are most likely programming errors. If this is really what " "you want, you can manually convert both objects to a common " "Comparable type before performing the comparison. If you think " "you have made your types Comparable but you see this, perhaps you " "forgot to define some of the necessary methods for an automatic " "model of Comparable to kick in. A possible culprit is defining " "'operator==' but not 'operator!='."); return hana::false_c; } }; // Cross-type overload template struct equal_impl::value && !detail::EqualityComparable::value >> { using C = typename hana::common::type; template static constexpr auto apply(X&& x, Y&& y) { return hana::equal(hana::to(static_cast(x)), hana::to(static_cast(y))); } }; ////////////////////////////////////////////////////////////////////////// // Model for EqualityComparable data types ////////////////////////////////////////////////////////////////////////// template struct equal_impl::value>> { template static constexpr auto apply(X&& x, Y&& y) { return static_cast(x) == static_cast(y); } }; ////////////////////////////////////////////////////////////////////////// // Model for Constants wrapping a Comparable ////////////////////////////////////////////////////////////////////////// template struct equal_impl::value && Comparable::value >> { template static constexpr auto apply(X const&, Y const&) { constexpr auto eq = hana::equal(hana::value(), hana::value()); constexpr bool truth_value = hana::if_(eq, true, false); return hana::bool_{}; } }; ////////////////////////////////////////////////////////////////////////// // Comparable for Products ////////////////////////////////////////////////////////////////////////// template struct equal_impl::value && hana::Product::value>> { template static constexpr auto apply(X const& x, Y const& y) { return hana::and_( hana::equal(hana::first(x), hana::first(y)), hana::equal(hana::second(x), hana::second(y)) ); } }; ////////////////////////////////////////////////////////////////////////// // Comparable for Sequences ////////////////////////////////////////////////////////////////////////// namespace detail { template struct compare_finite_sequences { Xs const& xs; Ys const& ys; template constexpr auto apply(hana::false_, hana::true_) const { return compare_finite_sequences::apply( hana::bool_{}, hana::if_(hana::equal(hana::at_c(xs), hana::at_c(ys)), hana::true_c, hana::false_c) ); } template constexpr auto apply(hana::false_, hana::false_) const { return hana::false_c; } template constexpr auto apply(hana::true_, Result r) const { return r; } template constexpr bool apply(hana::false_, bool b) const { return b && compare_finite_sequences::apply( hana::bool_{}, hana::if_(hana::equal(hana::at_c(xs), hana::at_c(ys)), hana::true_c, hana::false_c) ); } }; } template struct equal_impl::value && hana::Sequence::value>> { template static constexpr auto apply(Xs const& xs, Ys const& ys) { constexpr std::size_t xs_size = decltype(hana::length(xs))::value; constexpr std::size_t ys_size = decltype(hana::length(ys))::value; detail::compare_finite_sequences comp{xs, ys}; return comp.template apply<0>(hana::bool_{}, hana::bool_{}); } }; namespace detail { template struct compare_struct_members { X const& x; Y const& y; template constexpr auto operator()(Member&& member) const { auto accessor = hana::second(static_cast(member)); return hana::equal(accessor(x), accessor(y)); } }; } template struct equal_impl::value && !detail::EqualityComparable::value >> { template static constexpr auto apply(X const& x, Y const& y) { return hana::all_of(hana::accessors(), detail::compare_struct_members{x, y}); } }; BOOST_HANA_NAMESPACE_END #endif // !BOOST_HANA_EQUAL_HPP