diff --git a/include/boost/operators.hpp b/include/boost/operators.hpp index 7dce7df..75f3e6b 100644 --- a/include/boost/operators.hpp +++ b/include/boost/operators.hpp @@ -100,6 +100,11 @@ #include #include #include +#if defined(__cpp_impl_three_way_comparison) +#include +#include +#include +#endif #if defined(__sgi) && !defined(__GNUC__) # pragma set woff 1234 @@ -158,9 +163,21 @@ struct less_than_comparable1 : B template > struct equality_comparable2 : B { +#if defined(__cpp_impl_three_way_comparison) + template< typename R = decltype(boost::declval< T const& >() == boost::declval< U const& >()) > + friend BOOST_OPERATORS_CONSTEXPR + typename boost::enable_if_c< !boost::is_same< R, bool >::value, bool >::type + operator==(const U& y, const T& x) { return x == y; } + + template< typename R = decltype(boost::declval< T const& >() == boost::declval< U const& >()) > + friend BOOST_OPERATORS_CONSTEXPR + typename boost::enable_if_c< !boost::is_same< R, bool >::value, bool >::type + operator!=(const U& y, const T& x) { return !static_cast(x == y); } +#else friend BOOST_OPERATORS_CONSTEXPR bool operator==(const U& y, const T& x) { return x == y; } friend BOOST_OPERATORS_CONSTEXPR bool operator!=(const U& y, const T& x) { return !static_cast(x == y); } - friend BOOST_OPERATORS_CONSTEXPR bool operator!=(const T& y, const U& x) { return !static_cast(y == x); } +#endif + friend BOOST_OPERATORS_CONSTEXPR bool operator!=(const T& x, const U& y) { return !static_cast(x == y); } }; template > diff --git a/include/boost/operators_v1.hpp b/include/boost/operators_v1.hpp index e1c53e8..eb60dc2 100644 --- a/include/boost/operators_v1.hpp +++ b/include/boost/operators_v1.hpp @@ -144,9 +144,11 @@ struct less_than_comparable1 : B template > struct equality_comparable2 : B { +#if !defined(__cpp_impl_three_way_comparison) friend bool operator==(const U& y, const T& x) { return x == y; } friend bool operator!=(const U& y, const T& x) { return !static_cast(x == y); } - friend bool operator!=(const T& y, const U& x) { return !static_cast(y == x); } +#endif + friend bool operator!=(const T& x, const U& y) { return !static_cast(x == y); } }; template > diff --git a/test/operators_test.cpp b/test/operators_test.cpp index c1edf8f..fac3e5b 100644 --- a/test/operators_test.cpp +++ b/test/operators_test.cpp @@ -568,6 +568,25 @@ namespace int v; }; + // Test type designed specifically to test C++20 operator rewriting support + struct my_int : + public boost::equality_comparable2< my_int, int > + { + explicit my_int(int n) : m_n(n) {} + + operator int () const + { + return m_n; + } + + bool operator== (my_int that) + { + return that.m_n == m_n; + } + + int m_n; + }; + } // unnamed namespace @@ -932,5 +951,11 @@ main() cout << "Performed tests on MyLongInt objects.\n"; + my_int my_n = my_int(10); + + // Test if C++20 operator rewriting causes infinite recursion (https://github.com/boostorg/utility/issues/65) + BOOST_TEST(my_n == 10); + BOOST_TEST(my_n != 20); + return boost::report_errors(); }