1 #ifndef BOOST_DESCRIBE_OPERATORS_HPP_INCLUDED
2 #define BOOST_DESCRIBE_OPERATORS_HPP_INCLUDED
4 // Copyright 2020, 2021 Peter Dimov
5 // Distributed under the Boost Software License, Version 1.0.
6 // https://www.boost.org/LICENSE_1_0.txt
8 #include <boost/describe/detail/config.hpp>
10 #if defined(BOOST_DESCRIBE_CXX14)
12 #include <boost/describe/bases.hpp>
13 #include <boost/describe/members.hpp>
14 #include <boost/describe/modifiers.hpp>
15 #include <boost/mp11/algorithm.hpp>
16 #include <type_traits>
28 class Bd = describe_bases<T, mod_any_access>,
29 class Md = describe_members<T, mod_any_access>>
30 bool eq( T const& t1, T const& t2 )
34 mp11::mp_for_each<Bd>([&](auto D){
36 using B = typename decltype(D)::type;
37 r = r && (B const&)t1 == (B const&)t2;
41 mp11::mp_for_each<Md>([&](auto D){
43 r = r && t1.*D.pointer == t2.*D.pointer;
51 class Bd = describe_bases<T, mod_any_access>,
52 class Md = describe_members<T, mod_any_access>>
53 bool lt( T const& t1, T const& t2 )
57 mp11::mp_for_each<Bd>([&](auto D){
59 using B = typename decltype(D)::type;
60 if( r == 0 && (B const&)t1 < (B const&)t2 ) r = -1;
61 if( r == 0 && (B const&)t2 < (B const&)t1 ) r = +1;
65 mp11::mp_for_each<Md>([&](auto D){
67 if( r == 0 && t1.*D.pointer < t2.*D.pointer ) r = -1;
68 if( r == 0 && t2.*D.pointer < t1.*D.pointer ) r = +1;
75 template<class Os, class T,
76 class Bd = describe_bases<T, mod_any_access>,
77 class Md = describe_members<T, mod_any_access>>
78 void print( Os& os, T const& t )
84 mp11::mp_for_each<Bd>([&](auto D){
86 if( !first ) { os << ", "; }
89 using B = typename decltype(D)::type;
94 mp11::mp_for_each<Md>([&](auto D){
96 if( !first ) { os << ", "; }
99 os << "." << D.name << " = " << t.*D.pointer;
106 } // namespace detail
111 template<class T> std::enable_if_t<
112 has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
113 operator==( T const& t1, T const& t2 )
115 return detail::eq( t1, t2 );
118 template<class T> std::enable_if_t<
119 has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
120 operator!=( T const& t1, T const& t2 )
122 return !detail::eq( t1, t2 );
125 template<class T> std::enable_if_t<
126 has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
127 operator<( T const& t1, T const& t2 )
129 return detail::lt( t1, t2 );
132 template<class T> std::enable_if_t<
133 has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
134 operator>=( T const& t1, T const& t2 )
136 return !detail::lt( t1, t2 );
139 template<class T> std::enable_if_t<
140 has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
141 operator>( T const& t1, T const& t2 )
143 return detail::lt( t2, t1 );
146 template<class T> std::enable_if_t<
147 has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
148 operator<=( T const& t1, T const& t2 )
150 return !detail::lt( t2, t1 );
153 template<class T, class Ch, class Tr> std::enable_if_t<
154 has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value,
155 std::basic_ostream<Ch, Tr>&>
156 operator<<( std::basic_ostream<Ch, Tr>& os, T const& t )
159 detail::print( os, t );
163 } // namespace operators
165 } // namespace describe
168 #endif // defined(BOOST_DESCRIBE_CXX14)
170 #endif // #ifndef BOOST_DESCRIBE_OPERATORS_HPP_INCLUDED