diff --git a/include/boost/operators.hpp b/include/boost/operators.hpp index 156571c..aca5ea8 100644 --- a/include/boost/operators.hpp +++ b/include/boost/operators.hpp @@ -109,6 +109,17 @@ # 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 +#else +#define BOOST_OPS_CONSTEXPR +#endif +#else +#define BOOST_OPS_CONSTEXPR BOOST_CONSTEXPR +#endif + // In this section we supply the xxxx1 and xxxx2 forms of the operator // templates, which are explicitly targeted at the 1-type-argument and // 2-type-argument operator forms, respectively. @@ -132,34 +143,34 @@ template class empty_base {}; template > struct less_than_comparable2 : B { - friend bool operator<=(const T& x, const U& y) { return !static_cast(x > y); } - friend bool operator>=(const T& x, const U& y) { return !static_cast(x < y); } - friend bool operator>(const U& x, const T& y) { return y < x; } - friend bool operator<(const U& x, const T& y) { return y > x; } - friend bool operator<=(const U& x, const T& y) { return !static_cast(y < x); } - friend bool operator>=(const U& x, const T& y) { return !static_cast(y > x); } + 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); } }; template > struct less_than_comparable1 : B { - friend bool operator>(const T& x, const T& y) { return y < x; } - friend bool operator<=(const T& x, const T& y) { return !static_cast(y < x); } - friend bool operator>=(const T& x, const T& y) { return !static_cast(x < y); } + 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); } }; template > struct equality_comparable2 : B { - 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); } + 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); } }; template > struct equality_comparable1 : B { - friend bool operator!=(const T& x, const T& y) { return !static_cast(x == y); } + friend BOOST_OPS_CONSTEXPR bool operator!=(const T& x, const T& y) { return !static_cast(x == y); } }; // A macro which produces "name_2left" from "name". @@ -362,7 +373,7 @@ BOOST_BINARY_OPERATOR( right_shiftable, >> ) template > struct equivalent2 : B { - friend bool operator==(const T& x, const U& y) + friend BOOST_OPS_CONSTEXPR bool operator==(const T& x, const U& y) { return !static_cast(x < y) && !static_cast(x > y); } @@ -371,7 +382,7 @@ struct equivalent2 : B template > struct equivalent1 : B { - friend bool operator==(const T&x, const T&y) + friend BOOST_OPS_CONSTEXPR bool operator==(const T&x, const T&y) { return !static_cast(x < y) && !static_cast(y < x); } @@ -380,28 +391,28 @@ struct equivalent1 : B template > struct partially_ordered2 : B { - friend bool operator<=(const T& x, const U& y) + friend BOOST_OPS_CONSTEXPR bool operator<=(const T& x, const U& y) { return static_cast(x < y) || static_cast(x == y); } - friend bool operator>=(const T& x, const U& y) + friend BOOST_OPS_CONSTEXPR bool operator>=(const T& x, const U& y) { return static_cast(x > y) || static_cast(x == y); } - friend bool operator>(const U& x, const T& y) + friend BOOST_OPS_CONSTEXPR bool operator>(const U& x, const T& y) { return y < x; } - friend bool operator<(const U& x, const T& y) + friend BOOST_OPS_CONSTEXPR bool operator<(const U& x, const T& y) { return y > x; } - friend bool operator<=(const U& x, const T& y) + friend BOOST_OPS_CONSTEXPR bool operator<=(const U& x, const T& y) { return static_cast(y > x) || static_cast(y == x); } - friend bool operator>=(const U& x, const T& y) + friend BOOST_OPS_CONSTEXPR bool operator>=(const U& x, const T& y) { return static_cast(y < x) || static_cast(y == x); } }; template > struct partially_ordered1 : B { - friend bool operator>(const T& x, const T& y) + friend BOOST_OPS_CONSTEXPR bool operator>(const T& x, const T& y) { return y < x; } - friend bool operator<=(const T& x, const T& y) + friend BOOST_OPS_CONSTEXPR bool operator<=(const T& x, const T& y) { return static_cast(x < y) || static_cast(x == y); } - friend bool operator>=(const T& x, const T& y) + friend BOOST_OPS_CONSTEXPR bool operator>=(const T& x, const T& y) { return static_cast(y < x) || static_cast(x == y); } }; diff --git a/operators.htm b/operators.htm index d2c6682..3ae2bcc 100644 --- a/operators.htm +++ b/operators.htm @@ -454,7 +454,7 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); - + + + @@ -496,6 +498,9 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -513,6 +518,9 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -524,6 +532,9 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -537,6 +548,9 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -548,6 +562,8 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -560,6 +576,8 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -572,6 +590,8 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -584,6 +604,8 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -594,6 +616,8 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -606,6 +630,8 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -619,6 +645,8 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -630,6 +658,8 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -641,6 +671,8 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -651,6 +683,8 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -662,6 +696,8 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -673,6 +709,8 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -683,6 +721,8 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -694,6 +734,8 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -706,6 +748,8 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -717,6 +761,8 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -729,6 +775,8 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -740,6 +788,8 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -752,6 +802,8 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -762,6 +814,8 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -772,6 +826,8 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -784,6 +840,8 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -796,6 +854,8 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -808,6 +868,8 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -820,6 +882,8 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -831,6 +895,9 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -842,6 +909,9 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -856,6 +926,9 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); + + @@ -874,6 +947,9 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4); u.
Returns convertible to bool. See the Ordering Note. + +
Key @@ -482,6 +482,8 @@ const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4);
Supplied Operations RequirementsPropagates constexpr?
t < t1.
Return convertible to bool. See the Ordering Note.
Since C++11
+ (except MSVC < v19.22)
t < u. t > u.
Returns convertible to bool. See the Ordering Note.
Since C++11
+ (except MSVC < v19.22)
t == t1.
Return convertible to bool.
Since C++11
+ (except MSVC < v19.22)
t == u.
Return convertible to bool.
Since C++11
+ (except MSVC < v19.22)
T temp(t); temp += t1.
Return convertible to T. See the Symmetry Note.
No
T temp(t); temp += u.
Return convertible to T. See the Symmetry Note.
No
T temp(t); temp -= t1.
Return convertible to T. See the Symmetry Note.
No
T temp(t); temp -= u.
Return convertible to T. See the Symmetry Note.
No
T temp(u); temp -= t.
Return convertible to T.
No
T temp(t); temp *= t1.
Return convertible to T. See the Symmetry Note.
No
T temp(t); temp *= u.
Return convertible to T. See the Symmetry Note.
No
T temp(t); temp /= t1.
Return convertible to T. See the Symmetry Note.
No
T temp(t); temp /= u.
Return convertible to T. See the Symmetry Note.
No
T temp(u); temp /= t.
Return convertible to T.
No
T temp(t); temp %= t1.
Return convertible to T. See the Symmetry Note.
No
T temp(t); temp %= u.
Return convertible to T. See the Symmetry Note.
No
T temp(u); temp %= t.
Return convertible to T.
No
T temp(t); temp |= t1.
Return convertible to T. See the Symmetry Note.
No
T temp(t); temp |= u.
Return convertible to T. See the Symmetry Note.
No
T temp(t); temp &= t1.
Return convertible to T. See the Symmetry Note.
No
T temp(t); temp &= u.
Return convertible to T. See the Symmetry Note.
No
T temp(t); temp ^= t1.
Return convertible to T. See the Symmetry Note.
No
T temp(t); temp ^= u.
Return convertible to T. See the Symmetry Note.
No
T temp(t); ++t
Return convertible to T.
No
T temp(t); --t;
Return convertible to T.
No
T temp(t); temp <<= t1.
Return convertible to T. See the Symmetry Note.
No
T temp(t); temp <<= u.
Return convertible to T. See the Symmetry Note.
No
T temp(t); temp >>= t1.
Return convertible to T. See the Symmetry Note.
No
T temp(t); temp >>= u.
Return convertible to T. See the Symmetry Note.
No
t < t1.
Return convertible to bool. See the Ordering Note.
Since C++11
+ (except MSVC < v19.22)
t < u. t > u.
Returns convertible to bool. See the Ordering Note.
Since C++11
+ (except MSVC < v19.22)
t < t1. t == t1.
Returns convertible to bool. See the Ordering Note.
Since C++11
+ (except MSVC < v19.22)
Since C++11
+ (except MSVC < v19.22)
diff --git a/test/operators_test.cpp b/test/operators_test.cpp index 6cf7a76..a98d6f6 100644 --- a/test/operators_test.cpp +++ b/test/operators_test.cpp @@ -50,9 +50,9 @@ namespace void operator!() const; public: - convertible_to_bool( const bool value ) : _value( value ) {} + BOOST_OPS_CONSTEXPR convertible_to_bool( const bool value ) : _value( value ) {} - operator unspecified_bool_type() const + BOOST_OPS_CONSTEXPR operator unspecified_bool_type() const { return _value ? &convertible_to_bool::_value : 0; } }; @@ -64,12 +64,12 @@ namespace , boost::shiftable > { public: - explicit Wrapped1( T v = T() ) : _value(v) {} - T value() const { return _value; } + BOOST_OPS_CONSTEXPR explicit Wrapped1( T v = T() ) : _value(v) {} + BOOST_OPS_CONSTEXPR T value() const { return _value; } - convertible_to_bool operator<(const Wrapped1& x) const + BOOST_OPS_CONSTEXPR convertible_to_bool operator<(const Wrapped1& x) const { return _value < x._value; } - convertible_to_bool operator==(const Wrapped1& x) const + BOOST_OPS_CONSTEXPR convertible_to_bool operator==(const Wrapped1& x) const { return _value == x._value; } Wrapped1& operator+=(const Wrapped1& x) @@ -92,8 +92,8 @@ namespace { _value <<= x._value; return *this; } Wrapped1& operator>>=(const Wrapped1& x) { _value >>= x._value; return *this; } - Wrapped1& operator++() { ++_value; return *this; } - Wrapped1& operator--() { --_value; return *this; } + Wrapped1& operator++() { ++_value; return *this; } + Wrapped1& operator--() { --_value; return *this; } private: T _value; @@ -932,5 +932,31 @@ 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(); }