#ifndef BOOST_DESCRIBE_OPERATORS_HPP_INCLUDED #define BOOST_DESCRIBE_OPERATORS_HPP_INCLUDED // Copyright 2020, 2021 Peter Dimov // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt #include #if defined(BOOST_DESCRIBE_CXX14) #include #include #include #include #include #include namespace boost { namespace describe { namespace detail { template, class Md = describe_members> bool eq( T const& t1, T const& t2 ) { bool r = true; mp11::mp_for_each([&](auto D){ using B = typename decltype(D)::type; r = r && (B const&)t1 == (B const&)t2; }); mp11::mp_for_each([&](auto D){ r = r && t1.*D.pointer == t2.*D.pointer; }); return r; } template, class Md = describe_members> bool lt( T const& t1, T const& t2 ) { int r = 0; mp11::mp_for_each([&](auto D){ using B = typename decltype(D)::type; if( r == 0 && (B const&)t1 < (B const&)t2 ) r = -1; if( r == 0 && (B const&)t2 < (B const&)t1 ) r = +1; }); mp11::mp_for_each([&](auto D){ if( r == 0 && t1.*D.pointer < t2.*D.pointer ) r = -1; if( r == 0 && t2.*D.pointer < t1.*D.pointer ) r = +1; }); return r < 0; } template, class Md = describe_members> void print( Os& os, T const& t ) { os << "{"; bool first = true; mp11::mp_for_each([&](auto D){ if( !first ) { os << ", "; } first = false; using B = typename decltype(D)::type; os << (B const&)t; }); mp11::mp_for_each([&](auto D){ if( !first ) { os << ", "; } first = false; os << "." << D.name << " = " << t.*D.pointer; }); os << "}"; } } // namespace detail namespace operators { template std::enable_if_t< has_describe_bases::value && has_describe_members::value, bool> operator==( T const& t1, T const& t2 ) { return detail::eq( t1, t2 ); } template std::enable_if_t< has_describe_bases::value && has_describe_members::value, bool> operator!=( T const& t1, T const& t2 ) { return !detail::eq( t1, t2 ); } template std::enable_if_t< has_describe_bases::value && has_describe_members::value, bool> operator<( T const& t1, T const& t2 ) { return detail::lt( t1, t2 ); } template std::enable_if_t< has_describe_bases::value && has_describe_members::value, bool> operator>=( T const& t1, T const& t2 ) { return !detail::lt( t1, t2 ); } template std::enable_if_t< has_describe_bases::value && has_describe_members::value, bool> operator>( T const& t1, T const& t2 ) { return detail::lt( t2, t1 ); } template std::enable_if_t< has_describe_bases::value && has_describe_members::value, bool> operator<=( T const& t1, T const& t2 ) { return !detail::lt( t2, t1 ); } template std::enable_if_t< has_describe_bases::value && has_describe_members::value, std::basic_ostream&> operator<<( std::basic_ostream& os, T const& t ) { os.width( 0 ); detail::print( os, t ); return os; } } // namespace operators } // namespace describe } // namespace boost #endif // defined(BOOST_DESCRIBE_CXX14) #endif // #ifndef BOOST_DESCRIBE_OPERATORS_HPP_INCLUDED