Title
Heterogeneous comparisons in the standard library can result in ambiguities
Status
new
Section
[tuple.rel][allocator.globals][unique.ptr.special] [util.smartptr.shared.cmp][time.duration.comparisons] [time.point.comparisons][scoped.adaptor.operators] [reverse.iter.cmp][move.iter.op.comp]
Submitter
Richard Smith

Created on 2015-02-07.00:00:00 last changed 112 months ago

Messages

Date: 2015-02-07.00:00:00

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.

History
Date User Action Args
2015-02-07 00:00:00admincreate