operator==, !=, <, <=, >, >=, <=>(std::optional) (original) (raw)

Defined in header
Compare two optional objects
template< class T, class U > constexpr bool operator==( const optional<T>& lhs, const optional<U>& rhs ); (1) (since C++17)
template< class T, class U > constexpr bool operator!=( const optional<T>& lhs, const optional<U>& rhs ); (2) (since C++17)
template< class T, class U > constexpr bool operator<( const optional<T>& lhs, const optional<U>& rhs ); (3) (since C++17)
template< class T, class U > constexpr bool operator<=( const optional<T>& lhs, const optional<U>& rhs ); (4) (since C++17)
template< class T, class U > constexpr bool operator>( const optional<T>& lhs, const optional<U>& rhs ); (5) (since C++17)
template< class T, class U > constexpr bool operator>=( const optional<T>& lhs, const optional<U>& rhs ); (6) (since C++17)
template< class T, std::three_way_comparable_with<T> U > constexpr std::compare_three_way_result_t<T, U> operator<=>( const optional<T>& lhs, const optional<U>& rhs ); (7) (since C++20)
Compare an optional object with a nullopt
template< class T > constexpr bool operator==( const optional<T>& opt, std::nullopt_t ) noexcept; (8) (since C++17)
template< class T > constexpr bool operator==( std::nullopt_t, const optional<T>& opt ) noexcept; (9) (since C++17) (until C++20)
template< class T > constexpr bool operator!=( const optional<T>& opt, std::nullopt_t ) noexcept; (10) (since C++17) (until C++20)
template< class T > constexpr bool operator!=( std::nullopt_t, const optional<T>& opt ) noexcept; (11) (since C++17) (until C++20)
template< class T > constexpr bool operator<( const optional<T>& opt, std::nullopt_t ) noexcept; (12) (since C++17) (until C++20)
template< class T > constexpr bool operator<( std::nullopt_t, const optional<T>& opt ) noexcept; (13) (since C++17) (until C++20)
template< class T > constexpr bool operator<=( const optional<T>& opt, std::nullopt_t ) noexcept; (14) (since C++17) (until C++20)
template< class T > constexpr bool operator<=( std::nullopt_t, const optional<T>& opt ) noexcept; (15) (since C++17) (until C++20)
template< class T > constexpr bool operator>( const optional<T>& opt, std::nullopt_t ) noexcept; (16) (since C++17) (until C++20)
template< class T > constexpr bool operator>( std::nullopt_t, const optional<T>& opt ) noexcept; (17) (since C++17) (until C++20)
template< class T > constexpr bool operator>=( const optional<T>& opt, std::nullopt_t ) noexcept; (18) (since C++17) (until C++20)
template< class T > constexpr bool operator>=( std::nullopt_t, const optional<T>& opt ) noexcept; (19) (since C++17) (until C++20)
template< class T > constexpr std::strong_ordering operator<=>( const optional<T>& opt, std::nullopt_t ) noexcept; (20) (since C++20)
Compare an optional object with a value
template< class T, class U > constexpr bool operator==( const optional<T>& opt, const U& value ); (21) (since C++17)
template< class U, class T > constexpr bool operator==( const U& value, const optional<T>& opt ); (22) (since C++17)
template< class T, class U > constexpr bool operator!=( const optional<T>& opt, const U& value ); (23) (since C++17)
template< class U, class T > constexpr bool operator!=( const U& value, const optional<T>& opt ); (24) (since C++17)
template< class T, class U > constexpr bool operator<( const optional<T>& opt, const U& value ); (25) (since C++17)
template< class U, class T > constexpr bool operator<( const U& value, const optional<T>& opt ); (26) (since C++17)
template< class T, class U > constexpr bool operator<=( const optional<T>& opt, const U& value ); (27) (since C++17)
template< class U, class T > constexpr bool operator<=( const U& value, const optional<T>& opt ); (28) (since C++17)
template< class T, class U > constexpr bool operator>( const optional<T>& opt, const U& value ); (29) (since C++17)
template< class U, class T > constexpr bool operator>( const U& value, const optional<T>& opt ); (30) (since C++17)
template< class T, class U > constexpr bool operator>=( const optional<T>& opt, const U& value ); (31) (since C++17)
template< class U, class T > constexpr bool operator>=( const U& value, const optional<T>& opt ); (32) (since C++17)
template< class T, std::three_way_comparable_with<T> U > constexpr std::compare_three_way_result_t<T, U> operator<=>( const optional<T>& opt, const U& value ); (33) (since C++20)

Performs comparison operations on optional objects.

1-7) Compares two optional objects, lhs and rhs. The contained values are compared (using the corresponding operator of T) only if both lhs and rhs contain values. Otherwise,

1-6) Let @ denote the corresponding comparison operator, for each of these functions:

If the corresponding expression *lhs @ *rhs is ill-formed or its result is not convertible to bool, the program is ill-formed. (until C++26)
This overload participates in overload resolution only if the corresponding expression *lhs @ *rhs is well-formed and its result is convertible to bool. (since C++26)

8-20) Compares opt with a nullopt. Equivalent to (1-6) when comparing to an optional that does not contain a value.

The <, <=, >, >=, and != operators are synthesized from operator<=> and operator== respectively. (since C++20)

21-33) Compares opt with a value. The values are compared (using the corresponding operator of T) only if opt contains a value. Otherwise, opt is considered less than value.

21-32) Let @ denote the corresponding comparison operator, for each of these functions:

If the corresponding expression *opt @ value or value @ *opt (depending on the positions of the operands) is ill-formed or its result is not convertible to bool, the program is ill-formed. (until C++26)
This overload participates in overload resolution only if all following conditions are satisfied: U is not a specialization of std::optional. The corresponding expression *opt @ value or value @ *opt (depending on the positions of the operands) is well-formed and its result is convertible to bool. (since C++26)

[edit] Parameters

lhs, rhs, opt - an optional object to compare
value - value to compare to the contained value

[edit] Return value

  1. lhs.has_value() != rhs.has_value() ? false :
    (lhs.has_value() == false ? true : *lhs == *rhs)

  2. lhs.has_value() != rhs.has_value() ? true :
    (lhs.has_value() == false ? false : *lhs != *rhs)

  3. !rhs ? false : (!lhs ? true : *lhs < *rhs)

  4. !lhs ? true : (!rhs ? false : *lhs <= *rhs)

  5. !lhs ? false : (!rhs ? true : *lhs > *rhs)

  6. !rhs ? true : (!lhs ? false : *lhs >= *rhs)

  7. lhs && rhs ? *lhs <=> *rhs : lhs.has_value() <=> rhs.has_value()

8,9) !opt

10,11) opt.has_value()

  1. false

  2. opt.has_value()

  3. !opt

  4. true

  5. opt.has_value()

  6. false

  7. true

  8. !opt

  9. opt.has_value() <=> false

  10. opt.has_value() ? *opt == value : false

  11. opt.has_value() ? value == *opt : false

  12. opt.has_value() ? *opt != value : true

  13. opt.has_value() ? value != *opt : true

  14. opt.has_value() ? *opt < value : true

  15. opt.has_value() ? value < *opt : false

  16. opt.has_value() ? *opt <= value : true

  17. opt.has_value() ? value <= *opt : false

  18. opt.has_value() ? *opt > value : false

  19. opt.has_value() ? value > *opt : true

  20. opt.has_value() ? *opt >= value : false

  21. opt.has_value() ? value >= *opt : true

  22. opt.has_value() ? *opt <=> value : std::strong_ordering::less

[edit] Exceptions

1-7) May throw implementation-defined exceptions.

21-33) Throws when and what the comparison throws.

[edit] Notes

Feature-test macro Value Std Feature
__cpp_lib_constrained_equality 202403L (C++26) constrained comparison operators for std::optional

[edit] Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior
LWG 2945 C++17 order of template parameters inconsistent for compare-with-T cases made consistent