<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 3622: Misspecified transitivity of equivalence in &sect;[unord.req.general]</title>
<meta property="og:title" content="Issue 3622: Misspecified transitivity of equivalence in &sect;[unord.req.general]">
<meta property="og:description" content="C++ library issue. Status: C++23">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue3622.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#C++23">C++23</a> status.</em></p>
<h3 id="3622"><a href="lwg-defects.html#3622">3622</a>. Misspecified transitivity of equivalence in &sect;[unord.req.general]</h3>
<p><b>Section:</b> 23.2.8.1 <a href="https://wg21.link/unord.req.general">[unord.req.general]</a> <b>Status:</b> <a href="lwg-active.html#C++23">C++23</a>
 <b>Submitter:</b> Thomas K&ouml;ppe <b>Opened:</b> 2021-10-20 <b>Last modified:</b> 2023-11-22</p>
<p><b>Priority: </b>2
</p>
<p><b>View all issues with</b> <a href="lwg-status.html#C++23">C++23</a> status.</p>
<p><b>Discussion:</b></p>
<p>
The paper <a href="https://wg21.link/P2077R3" title=" Heterogeneous erasure overloads for associative containers">P2077R3</a> ("Heterogeneous erasure overloads for associative containers") 
adds a new variable <code>kx</code> with specific meaning for use in the Table of Unordered Associative 
Container Requirements, 23.2.8.1 <a href="https://wg21.link/unord.req.general">[unord.req.general]</a> p11, which is meant to stand for an 
equivalence class of heterogeneous values that can be compared with container keys.
<p/>
One property required of <code>kx</code> is transitivity of equality/equivalence, but this is currently specified as:
</p>
<blockquote><p>
"<code>kx</code> is a value such that [&hellip;] <code>(eq(r1, kx) &amp;&amp; eq(r1, r2)) == eq(r2, kx)</code> [&hellip;], 
where <code>r1</code> and <code>r2</code> are [any] keys".
</p></blockquote>
<p>
But this doesn't seem right. Transitivity means that <code>eq(r1, kx) &amp;&amp; eq(r1, r2)</code> being 
true implies <code>eq(r2, kx)</code> being true, but it does <em>not</em> imply that both sides are equal 
in general. In particular, <code>eq(r2, kx)</code> can be true even when <code>eq(r1, kx) &amp;&amp; eq(r1, r2)</code> 
is false.
<p/>
More abstractly, equality is transitive, but inequality is not.
<p/>
The new wording appears to have been copied from the pre-existing wording for the variable "<code>ke</code>", which 
suffers from the same problem, and so we propose to fix both cases.
</p>

<p><i>[2022-01-29; Reflector poll]</i></p>

<p>
Set priority to 2 after reflector poll.
</p>

<p><strong>Previous resolution [SUPERSEDED]:</strong></p>
<blockquote class="note">


<p>
This wording is relative to <a href="https://wg21.link/n4901">N4901</a>.
</p>

<ol>
<li><p>Modify 23.2.8.1 <a href="https://wg21.link/unord.req.general">[unord.req.general]</a> as indicated:</p>

<blockquote>
<ol style="list-style-type: none">
<li><p>[&hellip;]</p></li>
<li><p>(11.19) &mdash; <code>ke</code> is a value such that</p>
<ol style="list-style-type: none">
<li><p>(11.19.1) &mdash; <code>eq(r1, ke) == eq(ke, r1)</code>,</p></li>
<li><p>(11.19.2) &mdash; <code>hf(r1) == hf(ke)</code> if <code>eq(r1, ke)</code> is <code>true</code>, and</p></li>
<li><p>(11.19.3) &mdash; <del><code>(eq(r1, ke) &amp;&amp; eq(r1, r2)) == eq(r2, ke)</code></del><ins><code>eq(ke, r2)</code> 
is <code>true</code> if <code>eq(ke, r1) &amp;&amp; eq(r1, r2)</code> is <code>true</code></ins>,</p></li>
</ol>
<p>where <code>r1</code> and <code>r2</code> are keys of elements in <code>a_tran</code>,</p>
</li>
<li><p>(11.20) &mdash; <code>kx</code> is a value such that</p>
<ol style="list-style-type: none">
<li><p>(11.20.1) &mdash; <code>eq(r1, kx) == eq(kx, r1)</code>,</p></li>
<li><p>(11.20.2) &mdash; <code>hf(r1) == hf(kx)</code> if <code>eq(r1, kx)</code> is <code>true</code>,</p></li>
<li><p>(11.20.3) &mdash; <del><code>(eq(r1, kx) &amp;&amp; eq(r1, r2)) == eq(r2, kx)</code></del><ins><code>eq(kx, r2)</code> 
is <code>true</code> if <code>eq(kx, r1) &amp;&amp; eq(r1, r2)</code> is <code>true</code></ins>, and</p></li>
<li><p>(11.20.4) &mdash; <code>kx</code> is not convertible to either <code>iterator</code> or <code>const_iterator</code>,</p></li>
</ol>
<p>where <code>r1</code> and <code>r2</code> are keys of elements in <code>a_tran</code>,</p>
</li>
<li><p>[&hellip;]</p></li>
</ol>
</blockquote>
</li>
</ol>
</blockquote>

<p><i>[2022-02-07 Tim comments and provides updated wording]</i></p>

<p>
For heterogeneous lookup on unordered containers to work properly, we
need all keys comparing equal to the transparent key to be grouped
together. Since the only keys guaranteed to be so grouped are the ones
that are equal according to <code>eq</code>, we cannot allow 
<code>eq(r1, r2) == false</code> but <code>eq(r1, ke) == true &amp;&amp;
eq(r2, ke) == true</code>. The one-way
transitivity of equality is insufficient.
<p/>
We need both of the following:
</p>
<ul>
<li>
if <code>eq(r1, ke)</code> is <code>true</code> and <code>eq(r1, r2)</code> is <code>true</code> 
then <code>eq(r2, ke)</code> is <code>true</code>.
</li>
<li>
if <code>eq(r1, ke)</code> is <code>true</code> and <code>eq(r2, ke)</code> is <code>true</code> 
then <code>eq(r1, r2)</code> is <code>true</code>
</li>
</ul>

<p>
In a table:
</p>

<table border="1">
    <thead>
        <tr>
            <th>eq(r1, ke)</th>
            <th>eq(r1, r2)</th>
            <th>eq(r2, ke)</th>
            <th>OK?</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>T</td>
            <td>T</td>
            <td>T</td>
            <td>Y</td>
        </tr>
        <tr>
            <td>T</td>
            <td>T</td>
            <td>F</td>
            <td>N</td>
        </tr>
        <tr>
            <td>T</td>
            <td>F</td>
            <td>T</td>
            <td>N</td>
        </tr>
        <tr>
            <td>T</td>
            <td>F</td>
            <td>F</td>
            <td>Y</td>
        </tr>
        <tr>
            <td>F</td>
            <td>T</td>
            <td>T</td>
            <td>N</td>
        </tr>
        <tr>
            <td>F</td>
            <td>T</td>
            <td>F</td>
            <td>Y</td>
        </tr>
        <tr>
            <td>F</td>
            <td>F</td>
            <td>T</td>
            <td>Y</td>
        </tr>
        <tr>
            <td>F</td>
            <td>F</td>
            <td>F</td>
            <td>Y</td>
        </tr>
    </tbody>
</table>

<p><i>[Issaquah 2023-02-08; LWG]</i></p>

<p>Move to Immediate for C++23</p>

<p><i>[2023-02-13 Approved at February 2023 meeting in Issaquah. Status changed: Immediate &rarr; WP.]</i></p>



<p id="res-3622"><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/N4928" title=" Working Draft, Standard for Programming Language C++">N4928</a>.
</p>

<ol>
<li><p>Modify 23.2.8.1 <a href="https://wg21.link/unord.req.general">[unord.req.general]</a> as indicated:</p>

<blockquote>
<ol style="list-style-type: none">
<li><p>[&hellip;]</p></li>
<li><p>(10.20) &mdash; <code>ke</code> is a value such that</p>
<ol style="list-style-type: none">
<li><p>(10.20.1) &mdash; <code>eq(r1, ke) == eq(ke, r1)</code>,</p></li>
<li><p>(10.20.2) &mdash; <code>hf(r1) == hf(ke)</code> if <code>eq(r1, ke)</code> is <code>true</code>, and</p></li>
<li><p>(10.20.3) &mdash; <del><code>(eq(r1, ke) &amp;&amp; eq(r1, r2)) == eq(r2, ke)</code></del><ins>if any two of
<code>eq(r1, ke)</code>, <code>eq(r2, ke)</code> and <code>eq(r1, r2)</code> are <code>true</code>, then all three are <code>true</code></ins>,</p></li>
</ol>
<p>where <code>r1</code> and <code>r2</code> are keys of elements in <code>a_tran</code>,</p>
</li>
<li><p>(10.21) &mdash; <code>kx</code> is a value such that</p>
<ol style="list-style-type: none">
<li><p>(10.21.1) &mdash; <code>eq(r1, kx) == eq(kx, r1)</code>,</p></li>
<li><p>(10.21.2) &mdash; <code>hf(r1) == hf(kx)</code> if <code>eq(r1, kx)</code> is <code>true</code>,</p></li>
<li><p>(10.21.3) &mdash; <del><code>(eq(r1, kx) &amp;&amp; eq(r1, r2)) == eq(r2, kx)</code></del><ins>if any two of
<code>eq(r1, kx)</code>, <code>eq(r2, kx)</code> and <code>eq(r1, r2)</code> are <code>true</code>, then all three are <code>true</code></ins>, and</p></li>
<li><p>(10.21.4) &mdash; <code>kx</code> is not convertible to either <code>iterator</code> or <code>const_iterator</code>,</p></li>
</ol>
<p>where <code>r1</code> and <code>r2</code> are keys of elements in <code>a_tran</code>,</p>
</li>
<li><p>[&hellip;]</p></li>
</ol>
</blockquote>
</li>
</ol>





</body>
</html>
