1#ifndef BOOST_DESCRIBE_OPERATORS_HPP_INCLUDED
2#define BOOST_DESCRIBE_OPERATORS_HPP_INCLUDED
3
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
7
8#include <boost/describe/detail/config.hpp>
9
10#if defined(BOOST_DESCRIBE_CXX14)
11
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>
17#include <iosfwd>
18
19#if defined(_MSC_VER) && _MSC_VER == 1900
20# pragma warning(push)
21# pragma warning(disable: 4100) // unreferenced formal parameter
22#endif
23
24namespace boost
25{
26namespace describe
27{
28
29namespace detail
30{
31
32template<class T,
33 class Bd = describe::describe_bases<T, mod_any_access>,
34 class Md = describe::describe_members<T, mod_any_access>>
35bool eq( T const& t1, T const& t2 )
36{
37 bool r = true;
38
39 mp11::mp_for_each<Bd>([&](auto D){
40
41 using B = typename decltype(D)::type;
42 r = r && (B const&)t1 == (B const&)t2;
43
44 });
45
46 mp11::mp_for_each<Md>([&](auto D){
47
48 r = r && t1.*D.pointer == t2.*D.pointer;
49
50 });
51
52 return r;
53}
54
55template<class T,
56 class Bd = describe::describe_bases<T, mod_any_access>,
57 class Md = describe::describe_members<T, mod_any_access>>
58bool lt( T const& t1, T const& t2 )
59{
60 int r = 0;
61
62 mp11::mp_for_each<Bd>([&](auto D){
63
64 using B = typename decltype(D)::type;
65 if( r == 0 && (B const&)t1 < (B const&)t2 ) r = -1;
66 if( r == 0 && (B const&)t2 < (B const&)t1 ) r = +1;
67
68 });
69
70 mp11::mp_for_each<Md>([&](auto D){
71
72 if( r == 0 && t1.*D.pointer < t2.*D.pointer ) r = -1;
73 if( r == 0 && t2.*D.pointer < t1.*D.pointer ) r = +1;
74
75 });
76
77 return r < 0;
78}
79
80template<class Os, class T,
81 class Bd = describe::describe_bases<T, mod_any_access>,
82 class Md = describe::describe_members<T, mod_any_access>>
83void print( Os& os, T const& t )
84{
85 os << "{";
86
87 bool first = true;
88
89 mp11::mp_for_each<Bd>([&](auto D){
90
91 if( !first ) { os << ", "; }
92 first = false;
93
94 using B = typename decltype(D)::type;
95 os << (B const&)t;
96
97 });
98
99 mp11::mp_for_each<Md>([&](auto D){
100
101 if( !first ) { os << ", "; }
102 first = false;
103
104 os << "." << D.name << " = " << t.*D.pointer;
105
106 });
107
108 os << "}";
109}
110
111} // namespace detail
112
113namespace operators
114{
115
116template<class T> std::enable_if_t<
117 has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
118 operator==( T const& t1, T const& t2 )
119{
120 return detail::eq( t1, t2 );
121}
122
123template<class T> std::enable_if_t<
124 has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
125 operator!=( T const& t1, T const& t2 )
126{
127 return !detail::eq( t1, t2 );
128}
129
130template<class T> std::enable_if_t<
131 has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
132 operator<( T const& t1, T const& t2 )
133{
134 return detail::lt( t1, t2 );
135}
136
137template<class T> std::enable_if_t<
138 has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
139 operator>=( T const& t1, T const& t2 )
140{
141 return !detail::lt( t1, t2 );
142}
143
144template<class T> std::enable_if_t<
145 has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
146 operator>( T const& t1, T const& t2 )
147{
148 return detail::lt( t2, t1 );
149}
150
151template<class T> std::enable_if_t<
152 has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
153 operator<=( T const& t1, T const& t2 )
154{
155 return !detail::lt( t2, t1 );
156}
157
158template<class T, class Ch, class Tr> std::enable_if_t<
159 has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value,
160 std::basic_ostream<Ch, Tr>&>
161 operator<<( std::basic_ostream<Ch, Tr>& os, T const& t )
162{
163 os.width( 0 );
164 detail::print( os, t );
165 return os;
166}
167
168} // namespace operators
169
170} // namespace describe
171} // namespace boost
172
173#if defined(_MSC_VER) && _MSC_VER == 1900
174# pragma warning(pop)
175#endif
176
177#endif // defined(BOOST_DESCRIBE_CXX14)
178
179#endif // #ifndef BOOST_DESCRIBE_OPERATORS_HPP_INCLUDED
180

source code of boost/libs/describe/include/boost/describe/operators.hpp