This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.

### 2472. Heterogeneous comparisons in the standard library can result in ambiguities

Section: 20.5.8 [tuple.rel], 20.10.9.3 [allocator.globals], 20.11.1.6 [unique.ptr.special], 20.11.3.8 [util.smartptr.shared.cmp], 27.5.7 [time.duration.comparisons], 27.6.7 [time.point.comparisons], 20.13.5 [scoped.adaptor.operators], 23.5.1.8 [reverse.iter.cmp], 23.5.3.8 [move.iter.op.comp] Status: New Submitter: Richard Smith Opened: 2015-02-07 Last modified: 2021-06-06

Priority: 3

View other active issues in [tuple.rel].

View all other issues in [tuple.rel].

View all issues with New status.

Discussion:

The standard library specifies a lot of heterogeneous comparison operators. For instance:

>     template<class... TTypes, class... UTypes>
>     constexpr bool operator!=(const tuple<TTypes...>&, const tuple<UTypes...>&);

This has an unfortunate consequence:

>     #include <tuple>
>     #include <utility>

>     using namespace std::rel_ops;
>     std::tuple<int> a(0);
>     bool b = a != a;

The last line here is ill-formed due to ambiguity: it might be `rel_ops::operator!=`, and it might be the heterogeneous tuple `operator!=`. These are not partially ordered, because they have different constraints: `rel_ops` requires the types to match, whereas the tuple comparison requires both types to be tuples (but not to match). The same thing happens for user code that defines its own unconstrained '`template<typename T> operator!=(const T&, const T&)`' rather than using `rel_ops`.

One straightforward fix would be to add a homogeneous overload for each heterogeneous comparison:

>     template<class... TTypes>
>     constexpr bool operator!=(const tuple<TTypes...>&, const tuple<TTypes...>&);

> This is then unambiguously chosen over the other options in the preceding case. FWIW, libstdc++ already does this in some cases.

Proposed resolution: