Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:38:02

0001 /*!
0002 @file
0003 Defines `boost::hana::equal`.
0004 
0005 Copyright Louis Dionne 2013-2022
0006 Distributed under the Boost Software License, Version 1.0.
0007 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
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     //! @cond
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     //! @endcond
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             // Delay the static_assert by ensuring T_ is dependent.
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     // Cross-type overload
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     // Model for EqualityComparable data types
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     // Model for Constants wrapping a Comparable
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     // Comparable for Products
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     // Comparable for Sequences
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 }} // end namespace boost::hana
0205 
0206 #endif // !BOOST_HANA_EQUAL_HPP