File indexing completed on 2025-01-30 09:35:26
0001 #ifndef BOOST_DESCRIBE_OPERATORS_HPP_INCLUDED
0002 #define BOOST_DESCRIBE_OPERATORS_HPP_INCLUDED
0003
0004
0005
0006
0007
0008 #include <boost/describe/detail/config.hpp>
0009
0010 #if defined(BOOST_DESCRIBE_CXX14)
0011
0012 #include <boost/describe/bases.hpp>
0013 #include <boost/describe/members.hpp>
0014 #include <boost/describe/modifiers.hpp>
0015 #include <boost/mp11/algorithm.hpp>
0016 #include <type_traits>
0017 #include <iosfwd>
0018
0019 #if defined(_MSC_VER) && _MSC_VER == 1900
0020 # pragma warning(push)
0021 # pragma warning(disable: 4100)
0022 #endif
0023
0024 namespace boost
0025 {
0026 namespace describe
0027 {
0028
0029 namespace detail
0030 {
0031
0032 template<class T,
0033 class Bd = describe::describe_bases<T, mod_any_access>,
0034 class Md = describe::describe_members<T, mod_any_access>>
0035 bool eq( T const& t1, T const& t2 )
0036 {
0037 bool r = true;
0038
0039 mp11::mp_for_each<Bd>([&](auto D){
0040
0041 using B = typename decltype(D)::type;
0042 r = r && (B const&)t1 == (B const&)t2;
0043
0044 });
0045
0046 mp11::mp_for_each<Md>([&](auto D){
0047
0048 r = r && t1.*D.pointer == t2.*D.pointer;
0049
0050 });
0051
0052 return r;
0053 }
0054
0055 template<class T,
0056 class Bd = describe::describe_bases<T, mod_any_access>,
0057 class Md = describe::describe_members<T, mod_any_access>>
0058 bool lt( T const& t1, T const& t2 )
0059 {
0060 int r = 0;
0061
0062 mp11::mp_for_each<Bd>([&](auto D){
0063
0064 using B = typename decltype(D)::type;
0065 if( r == 0 && (B const&)t1 < (B const&)t2 ) r = -1;
0066 if( r == 0 && (B const&)t2 < (B const&)t1 ) r = +1;
0067
0068 });
0069
0070 mp11::mp_for_each<Md>([&](auto D){
0071
0072 if( r == 0 && t1.*D.pointer < t2.*D.pointer ) r = -1;
0073 if( r == 0 && t2.*D.pointer < t1.*D.pointer ) r = +1;
0074
0075 });
0076
0077 return r < 0;
0078 }
0079
0080 template<class Os, class T,
0081 class Bd = describe::describe_bases<T, mod_any_access>,
0082 class Md = describe::describe_members<T, mod_any_access>>
0083 void print( Os& os, T const& t )
0084 {
0085 os << "{";
0086
0087 bool first = true;
0088
0089 mp11::mp_for_each<Bd>([&](auto D){
0090
0091 if( !first ) { os << ", "; }
0092 first = false;
0093
0094 using B = typename decltype(D)::type;
0095 os << (B const&)t;
0096
0097 });
0098
0099 mp11::mp_for_each<Md>([&](auto D){
0100
0101 if( !first ) { os << ", "; }
0102 first = false;
0103
0104 os << "." << D.name << " = " << t.*D.pointer;
0105
0106 });
0107
0108 os << "}";
0109 }
0110
0111 }
0112
0113 namespace operators
0114 {
0115
0116 template<class T> std::enable_if_t<
0117 has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
0118 operator==( T const& t1, T const& t2 )
0119 {
0120 return detail::eq( t1, t2 );
0121 }
0122
0123 template<class T> std::enable_if_t<
0124 has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
0125 operator!=( T const& t1, T const& t2 )
0126 {
0127 return !detail::eq( t1, t2 );
0128 }
0129
0130 template<class T> std::enable_if_t<
0131 has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
0132 operator<( T const& t1, T const& t2 )
0133 {
0134 return detail::lt( t1, t2 );
0135 }
0136
0137 template<class T> std::enable_if_t<
0138 has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
0139 operator>=( T const& t1, T const& t2 )
0140 {
0141 return !detail::lt( t1, t2 );
0142 }
0143
0144 template<class T> std::enable_if_t<
0145 has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
0146 operator>( T const& t1, T const& t2 )
0147 {
0148 return detail::lt( t2, t1 );
0149 }
0150
0151 template<class T> std::enable_if_t<
0152 has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value, bool>
0153 operator<=( T const& t1, T const& t2 )
0154 {
0155 return !detail::lt( t2, t1 );
0156 }
0157
0158 template<class T, class Ch, class Tr> std::enable_if_t<
0159 has_describe_bases<T>::value && has_describe_members<T>::value && !std::is_union<T>::value,
0160 std::basic_ostream<Ch, Tr>&>
0161 operator<<( std::basic_ostream<Ch, Tr>& os, T const& t )
0162 {
0163 os.width( 0 );
0164 detail::print( os, t );
0165 return os;
0166 }
0167
0168 }
0169
0170 }
0171 }
0172
0173 #if defined(_MSC_VER) && _MSC_VER == 1900
0174 # pragma warning(pop)
0175 #endif
0176
0177 #endif
0178
0179 #endif