File indexing completed on 2025-01-18 09:38:02
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_HANA_EQUAL_HPP
0011 #define BOOST_HANA_EQUAL_HPP
0012
0013 #include <boost/hana/fwd/equal.hpp>
0014
0015 #include <boost/hana/accessors.hpp>
0016 #include <boost/hana/all_of.hpp>
0017 #include <boost/hana/and.hpp>
0018 #include <boost/hana/at.hpp>
0019 #include <boost/hana/bool.hpp>
0020 #include <boost/hana/concept/comparable.hpp>
0021 #include <boost/hana/concept/constant.hpp>
0022 #include <boost/hana/concept/product.hpp>
0023 #include <boost/hana/concept/sequence.hpp>
0024 #include <boost/hana/concept/struct.hpp>
0025 #include <boost/hana/config.hpp>
0026 #include <boost/hana/core/common.hpp>
0027 #include <boost/hana/core/to.hpp>
0028 #include <boost/hana/core/dispatch.hpp>
0029 #include <boost/hana/core/tag_of.hpp>
0030 #include <boost/hana/core/when.hpp>
0031 #include <boost/hana/detail/concepts.hpp>
0032 #include <boost/hana/detail/has_common_embedding.hpp>
0033 #include <boost/hana/detail/nested_to.hpp> // required by fwd decl
0034 #include <boost/hana/first.hpp>
0035 #include <boost/hana/if.hpp>
0036 #include <boost/hana/length.hpp>
0037 #include <boost/hana/second.hpp>
0038 #include <boost/hana/value.hpp>
0039
0040 #include <cstddef>
0041
0042
0043 namespace boost { namespace hana {
0044
0045 template <typename X, typename Y>
0046 constexpr auto equal_t::operator()(X&& x, Y&& y) const {
0047 using T = typename hana::tag_of<X>::type;
0048 using U = typename hana::tag_of<Y>::type;
0049 using Equal = equal_impl<T, U>;
0050 return Equal::apply(static_cast<X&&>(x), static_cast<Y&&>(y));
0051 }
0052
0053
0054 template <typename T, typename U, bool condition>
0055 struct equal_impl<T, U, when<condition>> : default_ {
0056 template <typename X, typename Y>
0057 static constexpr auto apply(X const&, Y const&) {
0058
0059 using T_ = typename hana::tag_of<X>::type;
0060 static_assert(!hana::is_convertible<T_, U>::value &&
0061 !hana::is_convertible<U, T_>::value,
0062 "No default implementation of hana::equal is provided for related "
0063 "types that can't be safely embedded into a common type, because "
0064 "those are most likely programming errors. If this is really what "
0065 "you want, you can manually convert both objects to a common "
0066 "Comparable type before performing the comparison. If you think "
0067 "you have made your types Comparable but you see this, perhaps you "
0068 "forgot to define some of the necessary methods for an automatic "
0069 "model of Comparable to kick in. A possible culprit is defining "
0070 "'operator==' but not 'operator!='.");
0071
0072 return hana::false_c;
0073 }
0074 };
0075
0076
0077 template <typename T, typename U>
0078 struct equal_impl<T, U, when<
0079 detail::has_nontrivial_common_embedding<Comparable, T, U>::value &&
0080 !detail::EqualityComparable<T, U>::value
0081 >> {
0082 using C = typename hana::common<T, U>::type;
0083 template <typename X, typename Y>
0084 static constexpr auto apply(X&& x, Y&& y) {
0085 return hana::equal(hana::to<C>(static_cast<X&&>(x)),
0086 hana::to<C>(static_cast<Y&&>(y)));
0087 }
0088 };
0089
0090
0091
0092
0093 template <typename T, typename U>
0094 struct equal_impl<T, U, when<detail::EqualityComparable<T, U>::value>> {
0095 template <typename X, typename Y>
0096 static constexpr auto apply(X&& x, Y&& y)
0097 { return static_cast<X&&>(x) == static_cast<Y&&>(y); }
0098 };
0099
0100
0101
0102
0103 template <typename C>
0104 struct equal_impl<C, C, when<
0105 hana::Constant<C>::value &&
0106 Comparable<typename C::value_type>::value
0107 >> {
0108 template <typename X, typename Y>
0109 static constexpr auto apply(X const&, Y const&) {
0110 constexpr auto eq = hana::equal(hana::value<X>(), hana::value<Y>());
0111 constexpr bool truth_value = hana::if_(eq, true, false);
0112 return hana::bool_<truth_value>{};
0113 }
0114 };
0115
0116
0117
0118
0119 template <typename T, typename U>
0120 struct equal_impl<T, U, when<hana::Product<T>::value && hana::Product<U>::value>> {
0121 template <typename X, typename Y>
0122 static constexpr auto apply(X const& x, Y const& y) {
0123 return hana::and_(
0124 hana::equal(hana::first(x), hana::first(y)),
0125 hana::equal(hana::second(x), hana::second(y))
0126 );
0127 }
0128 };
0129
0130
0131
0132
0133 namespace detail {
0134 template <typename Xs, typename Ys, std::size_t Length>
0135 struct compare_finite_sequences {
0136 Xs const& xs;
0137 Ys const& ys;
0138
0139 template <std::size_t i>
0140 constexpr auto apply(hana::false_, hana::true_) const {
0141 return compare_finite_sequences::apply<i+1>(
0142 hana::bool_<i+1 == Length>{},
0143 hana::if_(hana::equal(hana::at_c<i>(xs), hana::at_c<i>(ys)),
0144 hana::true_c, hana::false_c)
0145 );
0146 }
0147
0148 template <std::size_t i>
0149 constexpr auto apply(hana::false_, hana::false_) const
0150 { return hana::false_c; }
0151
0152 template <std::size_t i, typename Result>
0153 constexpr auto apply(hana::true_, Result r) const
0154 { return r; }
0155
0156 template <std::size_t i>
0157 constexpr bool apply(hana::false_, bool b) const {
0158 return b && compare_finite_sequences::apply<i+1>(
0159 hana::bool_<i+1 == Length>{},
0160 hana::if_(hana::equal(hana::at_c<i>(xs), hana::at_c<i>(ys)),
0161 hana::true_c, hana::false_c)
0162 );
0163 }
0164 };
0165 }
0166
0167 template <typename T, typename U>
0168 struct equal_impl<T, U, when<Sequence<T>::value && hana::Sequence<U>::value>> {
0169 template <typename Xs, typename Ys>
0170 static constexpr auto apply(Xs const& xs, Ys const& ys) {
0171 constexpr std::size_t xs_size = decltype(hana::length(xs))::value;
0172 constexpr std::size_t ys_size = decltype(hana::length(ys))::value;
0173 detail::compare_finite_sequences<Xs, Ys, xs_size> comp{xs, ys};
0174 return comp.template apply<0>(hana::bool_<xs_size == 0>{},
0175 hana::bool_<xs_size == ys_size>{});
0176 }
0177 };
0178
0179 namespace detail {
0180 template <typename X, typename Y>
0181 struct compare_struct_members {
0182 X const& x;
0183 Y const& y;
0184
0185 template <typename Member>
0186 constexpr auto operator()(Member&& member) const {
0187 auto accessor = hana::second(static_cast<Member&&>(member));
0188 return hana::equal(accessor(x), accessor(y));
0189 }
0190 };
0191 }
0192
0193 template <typename S>
0194 struct equal_impl<S, S, when<
0195 hana::Struct<S>::value &&
0196 !detail::EqualityComparable<S, S>::value
0197 >> {
0198 template <typename X, typename Y>
0199 static constexpr auto apply(X const& x, Y const& y) {
0200 return hana::all_of(hana::accessors<S>(),
0201 detail::compare_struct_members<X, Y>{x, y});
0202 }
0203 };
0204 }}
0205
0206 #endif