diff --git a/include/boost/operators.hpp b/include/boost/operators.hpp index aca5ea8..7dce7df 100644 --- a/include/boost/operators.hpp +++ b/include/boost/operators.hpp @@ -109,15 +109,11 @@ # pragma warning( disable : 4284 ) // complaint about return type of #endif // operator-> not begin a UDT -// Define BOOST_OPS_CONSTEXPR to be like BOOST_CONSTEXPR but empty under MSVC < v19.22 -#ifdef BOOST_MSVC -#if BOOST_MSVC_FULL_VER >= 192200000 -#define BOOST_OPS_CONSTEXPR constexpr +// Define BOOST_OPERATORS_CONSTEXPR to be like BOOST_CONSTEXPR but empty under MSVC < v19.22 +#if BOOST_WORKAROUND(BOOST_MSVC, < 1922) +#define BOOST_OPERATORS_CONSTEXPR #else -#define BOOST_OPS_CONSTEXPR -#endif -#else -#define BOOST_OPS_CONSTEXPR BOOST_CONSTEXPR +#define BOOST_OPERATORS_CONSTEXPR BOOST_CONSTEXPR #endif // In this section we supply the xxxx1 and xxxx2 forms of the operator @@ -143,34 +139,34 @@ template class empty_base {}; template > struct less_than_comparable2 : B { - friend BOOST_OPS_CONSTEXPR bool operator<=(const T& x, const U& y) { return !static_cast(x > y); } - friend BOOST_OPS_CONSTEXPR bool operator>=(const T& x, const U& y) { return !static_cast(x < y); } - friend BOOST_OPS_CONSTEXPR bool operator>(const U& x, const T& y) { return y < x; } - friend BOOST_OPS_CONSTEXPR bool operator<(const U& x, const T& y) { return y > x; } - friend BOOST_OPS_CONSTEXPR bool operator<=(const U& x, const T& y) { return !static_cast(y < x); } - friend BOOST_OPS_CONSTEXPR bool operator>=(const U& x, const T& y) { return !static_cast(y > x); } + friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const T& x, const U& y) { return !static_cast(x > y); } + friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const T& x, const U& y) { return !static_cast(x < y); } + friend BOOST_OPERATORS_CONSTEXPR bool operator>(const U& x, const T& y) { return y < x; } + friend BOOST_OPERATORS_CONSTEXPR bool operator<(const U& x, const T& y) { return y > x; } + friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const U& x, const T& y) { return !static_cast(y < x); } + friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const U& x, const T& y) { return !static_cast(y > x); } }; template > struct less_than_comparable1 : B { - friend BOOST_OPS_CONSTEXPR bool operator>(const T& x, const T& y) { return y < x; } - friend BOOST_OPS_CONSTEXPR bool operator<=(const T& x, const T& y) { return !static_cast(y < x); } - friend BOOST_OPS_CONSTEXPR bool operator>=(const T& x, const T& y) { return !static_cast(x < y); } + friend BOOST_OPERATORS_CONSTEXPR bool operator>(const T& x, const T& y) { return y < x; } + friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const T& x, const T& y) { return !static_cast(y < x); } + friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const T& x, const T& y) { return !static_cast(x < y); } }; template > struct equality_comparable2 : B { - friend BOOST_OPS_CONSTEXPR bool operator==(const U& y, const T& x) { return x == y; } - friend BOOST_OPS_CONSTEXPR bool operator!=(const U& y, const T& x) { return !static_cast(x == y); } - friend BOOST_OPS_CONSTEXPR bool operator!=(const T& y, const U& x) { return !static_cast(y == x); } + 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); } }; template > struct equality_comparable1 : B { - friend BOOST_OPS_CONSTEXPR bool operator!=(const T& x, const T& y) { return !static_cast(x == y); } + friend BOOST_OPERATORS_CONSTEXPR bool operator!=(const T& x, const T& y) { return !static_cast(x == y); } }; // A macro which produces "name_2left" from "name". @@ -373,7 +369,7 @@ BOOST_BINARY_OPERATOR( right_shiftable, >> ) template > struct equivalent2 : B { - friend BOOST_OPS_CONSTEXPR bool operator==(const T& x, const U& y) + friend BOOST_OPERATORS_CONSTEXPR bool operator==(const T& x, const U& y) { return !static_cast(x < y) && !static_cast(x > y); } @@ -382,7 +378,7 @@ struct equivalent2 : B template > struct equivalent1 : B { - friend BOOST_OPS_CONSTEXPR bool operator==(const T&x, const T&y) + friend BOOST_OPERATORS_CONSTEXPR bool operator==(const T&x, const T&y) { return !static_cast(x < y) && !static_cast(y < x); } @@ -391,28 +387,28 @@ struct equivalent1 : B template > struct partially_ordered2 : B { - friend BOOST_OPS_CONSTEXPR bool operator<=(const T& x, const U& y) + friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const T& x, const U& y) { return static_cast(x < y) || static_cast(x == y); } - friend BOOST_OPS_CONSTEXPR bool operator>=(const T& x, const U& y) + friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const T& x, const U& y) { return static_cast(x > y) || static_cast(x == y); } - friend BOOST_OPS_CONSTEXPR bool operator>(const U& x, const T& y) + friend BOOST_OPERATORS_CONSTEXPR bool operator>(const U& x, const T& y) { return y < x; } - friend BOOST_OPS_CONSTEXPR bool operator<(const U& x, const T& y) + friend BOOST_OPERATORS_CONSTEXPR bool operator<(const U& x, const T& y) { return y > x; } - friend BOOST_OPS_CONSTEXPR bool operator<=(const U& x, const T& y) + friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const U& x, const T& y) { return static_cast(y > x) || static_cast(y == x); } - friend BOOST_OPS_CONSTEXPR bool operator>=(const U& x, const T& y) + friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const U& x, const T& y) { return static_cast(y < x) || static_cast(y == x); } }; template > struct partially_ordered1 : B { - friend BOOST_OPS_CONSTEXPR bool operator>(const T& x, const T& y) + friend BOOST_OPERATORS_CONSTEXPR bool operator>(const T& x, const T& y) { return y < x; } - friend BOOST_OPS_CONSTEXPR bool operator<=(const T& x, const T& y) + friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const T& x, const T& y) { return static_cast(x < y) || static_cast(x == y); } - friend BOOST_OPS_CONSTEXPR bool operator>=(const T& x, const T& y) + friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const T& x, const T& y) { return static_cast(y < x) || static_cast(x == y); } }; diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 739edc0..55fdd44 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -21,6 +21,7 @@ run compressed_pair_final_test.cpp ; run iterators_test.cpp ; run operators_test.cpp ; +compile operators_constexpr_test.cpp ; compile result_of_test.cpp ; diff --git a/test/operators_constexpr_test.cpp b/test/operators_constexpr_test.cpp new file mode 100644 index 0000000..02d3186 --- /dev/null +++ b/test/operators_constexpr_test.cpp @@ -0,0 +1,59 @@ +/* +Copyright 2020 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ + +#include +#if !defined(BOOST_NO_CXX11_CONSTEXPR) && \ + (!defined(BOOST_MSVC) || (BOOST_MSVC >= 1922)) +#include +#include + +namespace { + +class Value + : boost::operators { +public: + BOOST_OPERATORS_CONSTEXPR explicit Value(int v) + : v_(v) { } + + BOOST_OPERATORS_CONSTEXPR bool + operator<(const Value& x) const { + return v_ < x.v_; + } + + BOOST_OPERATORS_CONSTEXPR bool + operator==(const Value& x) const { + return v_ == x.v_; + } + +private: + int v_; +}; + +} // namespace + +BOOST_STATIC_ASSERT(!static_cast(Value(1) == Value(2))); +BOOST_STATIC_ASSERT(Value(1) != Value(2)); +BOOST_STATIC_ASSERT(Value(1) < Value(2)); +BOOST_STATIC_ASSERT(Value(1) <= Value(2)); +BOOST_STATIC_ASSERT(!static_cast(Value(1) > Value(2))); +BOOST_STATIC_ASSERT(!static_cast(Value(1) >= Value(2))); + +BOOST_STATIC_ASSERT(!static_cast(Value(2) == Value(1))); +BOOST_STATIC_ASSERT(Value(2) != Value(1)); +BOOST_STATIC_ASSERT(!static_cast(Value(2) < Value(1))); +BOOST_STATIC_ASSERT(!static_cast(Value(2) <= Value(1))); +BOOST_STATIC_ASSERT(Value(2) > Value(1)); +BOOST_STATIC_ASSERT(Value(2) >= Value(1)); + +BOOST_STATIC_ASSERT(Value(1) == Value(1)); +BOOST_STATIC_ASSERT(!static_cast(Value(1) != Value(1))); +BOOST_STATIC_ASSERT(!static_cast(Value(1) < Value(1))); +BOOST_STATIC_ASSERT(Value(1) <= Value(1)); +BOOST_STATIC_ASSERT(!static_cast(Value(1) > Value(1))); +BOOST_STATIC_ASSERT(Value(1) >= Value(1)); +#endif diff --git a/test/operators_test.cpp b/test/operators_test.cpp index a98d6f6..c1edf8f 100644 --- a/test/operators_test.cpp +++ b/test/operators_test.cpp @@ -50,9 +50,9 @@ namespace void operator!() const; public: - BOOST_OPS_CONSTEXPR convertible_to_bool( const bool value ) : _value( value ) {} + convertible_to_bool( const bool value ) : _value( value ) {} - BOOST_OPS_CONSTEXPR operator unspecified_bool_type() const + operator unspecified_bool_type() const { return _value ? &convertible_to_bool::_value : 0; } }; @@ -64,12 +64,12 @@ namespace , boost::shiftable > { public: - BOOST_OPS_CONSTEXPR explicit Wrapped1( T v = T() ) : _value(v) {} - BOOST_OPS_CONSTEXPR T value() const { return _value; } + explicit Wrapped1( T v = T() ) : _value(v) {} + T value() const { return _value; } - BOOST_OPS_CONSTEXPR convertible_to_bool operator<(const Wrapped1& x) const + convertible_to_bool operator<(const Wrapped1& x) const { return _value < x._value; } - BOOST_OPS_CONSTEXPR convertible_to_bool operator==(const Wrapped1& x) const + convertible_to_bool operator==(const Wrapped1& x) const { return _value == x._value; } Wrapped1& operator+=(const Wrapped1& x) @@ -932,31 +932,5 @@ main() cout << "Performed tests on MyLongInt objects.\n"; -// Where C++11 constexpr is available, compile-time test some of the operators that are able to use it to propagate constexpr -#ifndef BOOST_NO_CXX11_CONSTEXPR -#if !defined(BOOST_MSVC) || (_MSC_VER >= 1922) - static_assert( ! static_cast( MyInt{ 1 } == MyInt{ 2 } ), "" ); - static_assert( MyInt{ 1 } != MyInt{ 2 }, "" ); - static_assert( MyInt{ 1 } < MyInt{ 2 }, "" ); - static_assert( MyInt{ 1 } <= MyInt{ 2 }, "" ); - static_assert( ! static_cast( MyInt{ 1 } > MyInt{ 2 } ), "" ); - static_assert( ! static_cast( MyInt{ 1 } >= MyInt{ 2 } ), "" ); - - static_assert( ! static_cast( MyInt{ 2 } == MyInt{ 1 } ), "" ); - static_assert( MyInt{ 2 } != MyInt{ 1 }, "" ); - static_assert( ! static_cast( MyInt{ 2 } < MyInt{ 1 } ), "" ); - static_assert( ! static_cast( MyInt{ 2 } <= MyInt{ 1 } ), "" ); - static_assert( MyInt{ 2 } > MyInt{ 1 }, "" ); - static_assert( MyInt{ 2 } >= MyInt{ 1 }, "" ); - - static_assert( MyInt{ 1 } == MyInt{ 1 }, "" ); - static_assert( ! static_cast( MyInt{ 1 } != MyInt{ 1 } ), "" ); - static_assert( ! static_cast( MyInt{ 1 } < MyInt{ 1 } ), "" ); - static_assert( MyInt{ 1 } <= MyInt{ 1 }, "" ); - static_assert( ! static_cast( MyInt{ 1 } > MyInt{ 1 } ), "" ); - static_assert( MyInt{ 1 } >= MyInt{ 1 }, "" ); -#endif -#endif - return boost::report_errors(); }