<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 2472: Heterogeneous comparisons in the standard library can result in ambiguities</title>
<meta property="og:title" content="Issue 2472: Heterogeneous comparisons in the standard library can result in ambiguities">
<meta property="og:description" content="C++ library issue. Status: New">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue2472.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#New">New</a> status.</em></p>
<h3 id="2472"><a href="lwg-active.html#2472">2472</a>. Heterogeneous comparisons in the standard library can result in ambiguities</h3>
<p><b>Section:</b> 22.4.9 <a href="https://wg21.link/tuple.rel">[tuple.rel]</a>, 20.2.10.3 <a href="https://wg21.link/allocator.globals">[allocator.globals]</a>, 20.3.1.6 <a href="https://wg21.link/unique.ptr.special">[unique.ptr.special]</a>, 20.3.2.2.8 <a href="https://wg21.link/util.smartptr.shared.cmp">[util.smartptr.shared.cmp]</a>, 30.5.7 <a href="https://wg21.link/time.duration.comparisons">[time.duration.comparisons]</a>, 30.6.7 <a href="https://wg21.link/time.point.comparisons">[time.point.comparisons]</a>, 20.6.5 <a href="https://wg21.link/scoped.adaptor.operators">[scoped.adaptor.operators]</a>, 24.5.1.8 <a href="https://wg21.link/reverse.iter.cmp">[reverse.iter.cmp]</a>, 24.5.4.8 <a href="https://wg21.link/move.iter.op.comp">[move.iter.op.comp]</a> <b>Status:</b> <a href="lwg-active.html#New">New</a>
 <b>Submitter:</b> Richard Smith <b>Opened:</b> 2015-02-07 <b>Last modified:</b> 2021-06-06</p>
<p><b>Priority: </b>3
</p>
<p><b>View other</b> <a href="lwg-index-open.html#tuple.rel">active issues</a> in [tuple.rel].</p>
<p><b>View all other</b> <a href="lwg-index.html#tuple.rel">issues</a> in [tuple.rel].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#New">New</a> status.</p>
<p><b>Discussion:</b></p>
<p>
The standard library specifies a lot of heterogeneous comparison operators. For instance:
</p>
<blockquote>
<pre>
template&lt;class... TTypes, class... UTypes&gt;
constexpr bool operator!=(const tuple&lt;TTypes...&gt;&amp;, const tuple&lt;UTypes...&gt;&amp;);
</pre>
</blockquote>
<p>
This has an unfortunate consequence:
</p>
<blockquote>
<pre>
#include &lt;tuple&gt;
#include &lt;utility&gt;

using namespace std::rel_ops;
std::tuple&lt;int&gt; a(0);
bool b = a != a;
</pre>
</blockquote>
<p>
The last line here is ill-formed due to ambiguity: it might be <code>rel_ops::operator!=</code>, and it might be the
heterogeneous tuple <code>operator!=</code>. These are not partially ordered, because they have different constraints:
<code>rel_ops</code> 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
'<code>template&lt;typename T&gt; operator!=(const T&amp;, const T&amp;)</code>' rather than using <code>rel_ops</code>.
<p/>
One straightforward fix would be to add a homogeneous overload for each heterogeneous comparison:
</p>
<blockquote>
<pre>
template&lt;class... TTypes&gt;
constexpr bool operator!=(const tuple&lt;TTypes...&gt;&amp;, const tuple&lt;TTypes...&gt;&amp;);
</pre>
<p>
This is then unambiguously chosen over the other options in the preceding case. FWIW, libstdc++ already does this
<a href="https://gcc.gnu.org/onlinedocs/gcc-4.6.4/libstdc++/api/a01065_source.html#l00788">in some cases</a>.
</p>
</blockquote>


<p id="res-2472"><b>Proposed resolution:</b></p>





</body>
</html>
