Title
optional<const T> doesn't compare with T
Status
c++17
Section
[optional.comp.with.t]
Submitter
Ville Voutilainen

Created on 2017-02-17.00:00:00 last changed 89 months ago

Messages

Date: 2017-03-03.22:08:49

Proposed resolution:

This wording is relative to N4640.

  1. Modify [optional.syn], header <optional> synopsis, as indicated:

    […]
    
    // [optional.relops], relational operators
    template <class T, class U>
    constexpr bool operator==(const optional<T>&, const optional<TU>&);
    template <class T, class U>
    constexpr bool operator!=(const optional<T>&, const optional<TU>&);
    template <class T, class U>
    constexpr bool operator<(const optional<T>&, const optional<TU>&);
    template <class T, class U>
    constexpr bool operator>(const optional<T>&, const optional<TU>&);
    template <class T, class U>
    constexpr bool operator<=(const optional<T>&, const optional<TU>&);
    template <class T, class U>
    constexpr bool operator>=(const optional<T>&, const optional<TU>&);
    
    […]
    
    // [optional.comp_with_t], comparison with T
    template <class T, class U> constexpr bool operator==(const optional<T>&, const TU&);
    template <class T, class U> constexpr bool operator==(const TU&, const optional<T>&);
    template <class T, class U> constexpr bool operator!=(const optional<T>&, const TU&);
    template <class T, class U> constexpr bool operator!=(const TU&, const optional<T>&);
    template <class T, class U> constexpr bool operator<(const optional<T>&, const TU&);
    template <class T, class U> constexpr bool operator<(const TU&, const optional<T>&);
    template <class T, class U> constexpr bool operator<=(const optional<T>&, const TU&);
    template <class T, class U> constexpr bool operator<=(const TU&, const optional<T>&);
    template <class T, class U> constexpr bool operator>(const optional<T>&, const TU&);
    template <class T, class U> constexpr bool operator>(const TU&, const optional<T>&);
    template <class T, class U> constexpr bool operator>=(const optional<T>&, const TU&);
    template <class T, class U> constexpr bool operator>=(const TU&, const optional<T>&);
    
  2. Modify [optional.relops] as indicated:

    template <class T, class U> constexpr bool operator==(const optional<T>& x, const optional<TU>& y);
    

    […]

    template <class T, class U> constexpr bool operator!=(const optional<T>& x, const optional<TU>& y);
    

    […]

    template <class T, class U> constexpr bool operator<(const optional<T>& x, const optional<TU>& y);
    

    […]

    template <class T, class U> constexpr bool operator>(const optional<T>& x, const optional<TU>& y);
    

    […]

    template <class T, class U> constexpr bool operator<=(const optional<T>& x, const optional<TU>& y);
    

    […]

    template <class T, class U> constexpr bool operator>=(const optional<T>& x, const optional<TU>& y);
    

    […]

  3. Modify [optional.comp_with_t] as indicated:

    template <class T, class U> constexpr bool operator==(const optional<T>& x, const TU& v);
    

    -?- Requires: The expression *x == v shall be well-formed and its result shall be convertible to bool. [Note: T need not be EqualityComparable. — end note]

    -1- Effects: Equivalent to: return bool(x) ? *x == v : false;

    template <class T, class U> constexpr bool operator==(const TU& v, const optional<T>& x);
    

    -?- Requires: The expression v == *x shall be well-formed and its result shall be convertible to bool.

    -2- Effects: Equivalent to: return bool(x) ? v == *x : false;

    template <class T, class U> constexpr bool operator!=(const optional<T>& x, const TU& v);
    

    -?- Requires: The expression *x != v shall be well-formed and its result shall be convertible to bool.

    -3- Effects: Equivalent to: return bool(x) ? *x != v : true;

    template <class T, class U> constexpr bool operator!=(const TU& v, const optional<T>& x);
    

    -?- Requires: The expression v != *x shall be well-formed and its result shall be convertible to bool.

    -4- Effects: Equivalent to: return bool(x) ? v != *x : true;

    template <class T, class U> constexpr bool operator<(const optional<T>& x, const TU& v);
    

    -?- Requires: The expression *x < v shall be well-formed and its result shall be convertible to bool.

    -5- Effects: Equivalent to: return bool(x) ? *x < v : true;

    template <class T, class U> constexpr bool operator<(const TU& v, const optional<T>& x);
    

    -?- Requires: The expression v < *x shall be well-formed and its result shall be convertible to bool.

    -6- Effects: Equivalent to: return bool(x) ? v < *x : false;

    template <class T, class U> constexpr bool operator<=(const optional<T>& x, const TU& v);
    

    -?- Requires: The expression *x <= v shall be well-formed and its result shall be convertible to bool.

    -7- Effects: Equivalent to: return bool(x) ? *x <= v : true;

    template <class T, class U> constexpr bool operator<=(const TU& v, const optional<T>& x);
    

    -?- Requires: The expression v <= *x shall be well-formed and its result shall be convertible to bool.

    -8- Effects: Equivalent to: return bool(x) ? v <= *x : false;

    template <class T, class U> constexpr bool operator>(const optional<T>& x, const TU& v);
    

    -?- Requires: The expression *x > v shall be well-formed and its result shall be convertible to bool.

    -9- Effects: Equivalent to: return bool(x) ? *x > v : false;

    template <class T, class U> constexpr bool operator>(const TU& v, const optional<T>& x);
    

    -?- Requires: The expression v > *x shall be well-formed and its result shall be convertible to bool.

    -10- Effects: Equivalent to: return bool(x) ? v > *x : true;

    template <class T, class U> constexpr bool operator>=(const optional<T>& x, const TU& v);
    

    -?- Requires: The expression *x >= v shall be well-formed and its result shall be convertible to bool.

    -11- Effects: Equivalent to: return bool(x) ? *x >= v : false;

    template <class T, class U> constexpr bool operator>=(const TU& v, const optional<T>& x);
    

    -?- Requires: The expression v >= *x shall be well-formed and its result shall be convertible to bool.

    -12- Effects: Equivalent to: return bool(x) ? v >= *x : true;

    
    
Date: 2017-03-03.22:08:49

[ Kona 2017-02-28 ]

Accepted as Immediate to avoid having break ABI later.

Date: 2017-02-17.00:00:00

Consider:

optional<const int> x = 42;
int y = 666;
x == y; // ill-formed

The comparison is ill-formed, because in [optional.comp_with_t]/1,

template <class T> constexpr bool operator==(const optional<T>& x, const T& v);

the T is deduced to be both const int and int, which is ill-formed.

Since it became apparent that the root cause of this issue is also causing difficulties with e.g. comparing optional<string> with literals etc., here's a p/r that

  1. adds requirements for optional's comparisons with T

  2. turns optional-optional comparisons into two-template-parameter templates, allowing comparing mixed optionals

  3. turns optional-T comparisons into two-template-parameter templates, allowing comparing optionals with T and types comparable with T

History
Date User Action Args
2017-07-30 20:15:43adminsetstatus: wp -> c++17
2017-03-05 23:46:08adminsetstatus: immediate -> wp
2017-03-03 22:08:49adminsetmessages: + msg9063
2017-03-03 22:08:49adminsetstatus: new -> immediate
2017-02-21 22:29:22adminsetmessages: + msg8972
2017-02-17 00:00:00admincreate