<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 1406: Support hashing smart-pointers based on owner</title>
<meta property="og:title" content="Issue 1406: Support hashing smart-pointers based on owner">
<meta property="og:description" content="C++ library issue. Status: NAD">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue1406.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#NAD">NAD</a> status.</em></p>
<h3 id="1406"><a href="lwg-closed.html#1406">1406</a>. Support hashing smart-pointers based on <i>owner</i></h3>
<p><b>Section:</b> 20.3.2.2 <a href="https://wg21.link/util.smartptr.shared">[util.smartptr.shared]</a> <b>Status:</b> <a href="lwg-active.html#NAD">NAD</a>
 <b>Submitter:</b> Japan <b>Opened:</b> 2010-08-25 <b>Last modified:</b> 2019-02-26</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View all other</b> <a href="lwg-index.html#util.smartptr.shared">issues</a> in [util.smartptr.shared].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#NAD">NAD</a> status.</p>
<p><b>Discussion:</b></p>
<p><b>Addresses JP-5</b></p>
<p>
Hash support based on ownership sharing should be
supplied for <code>shared_ptr</code> and <code>weak_ptr</code>.
For two <code>shared_ptr</code> objects <code>p</code> and <code>q</code>, two distinct
equivalence relations can be defined. One is based on
equivalence of pointer values, which is derived from the
expression <code>p.get() == q.get()</code> (hereafter called <i>address based
equivalence relation</i>), the other is based on
equivalence of ownership sharing, which is derived from
the expression <code>!p.owner_before(q) &amp;&amp; !q.owner_before(p)</code>
(hereafter called <i>ownership-based equivalence relation</i>).
These two equivalence relations are independent in
general. For example, a <code>shared_ptr</code> object created by the
constructor of the signature <code>shared_ptr(shared_ptr&lt;U>
const &amp;, T *)</code> could reveal a difference between these two
relations. Therefore, hash support based on each
equivalence relation should be supplied for <code>shared_ptr</code>.
However, while the standard library provides the hash
support for address-based one (20.9.11.6 paragraph 2), it
lacks the hash support for ownership-based one. In
addition, associative containers work well in combination
with the <code>shared_ptr</code>'s ownership-based comparison but
unordered associative containers don't. This is
inconsistent.
</p>
<p>
For the case of <code>weak_ptr</code>, hash support for the ownership based
equivalence relation can be safely defined on
<code>weak_ptr</code>s, and even on expired ones. The absence of
hash support for the ownership-based equivalence
relation is fatal, especially for expired <code>weak_ptr</code>s. And the
absence of such hash support precludes some quite
effective use-cases, e.g. erasing the <code>unordered_map</code> entry
of an expired <code>weak_ptr</code> key from a customized deleter
supplied to <code>shared_ptr</code>s.
</p>
<p>
Hash support for the ownership-based equivalence
relation cannot be provided by any user-defined manner
because information about ownership sharing is not
available to users at all. Therefore, the only way to provide
ownership-based hash support is to offer it intrusively by
the standard library.
</p>
<p>
As far as we know, such hash support is implementable.
Typical implementation of such hash function could return
the hash value of the pointer of the counter object that is
internally managed by <code>shared_ptr</code> and <code>weak_ptr</code>.
</p>

<p><i>[2010 Rapperswil:]</i></p>

<blockquote>
<p>No consensus to make this change at this time.</p>
</blockquote>

<p><i>[LEWG Kona 2017]</i></p>

<p>Recommend NAD: Needs a paper. Feature. Exposing an implementation detail (indirectly observable via hash).</p>



<p id="res-1406"><b>Proposed resolution:</b></p>
<p>
Add the following non-static member functions to
<code>shared_ptr</code> and <code>weak_ptr</code> class template;
</p>
<p>
Update [util.smartptr.shared], 20.9.11.2 paragraph 1
</p>
<pre>
namespace std{
template&lt;class T&gt; class shared_ptr {
public:
...
  <ins>size_t owner_hash() const;</ins>
...
};
}
</pre>
<p>
Update [util.smartptr.weak], 20.9.11.3 paragraph 1
</p>
<pre>
namespace std{
template&lt;class T&gt; class weak_ptr {
public:
...
  <ins>size_t owner_hash() const;</ins>
...
};
}
</pre>
<p>
These functions satisfy the following
requirements. Let <code>p</code> and <code>q</code> be objects of either
<code>shared_ptr</code> or <code>weak_ptr</code>, <code>H</code> be a hypothetical
function object type that satisfies the hash
requirements ([hash.requirements], 20.2.4) and <code>h</code> be an object of the
type <code>H</code>. The expression <code>p.owner_hash()</code> behaves
as if it were equivalent to the expression <code>h(p)</code>. In
addition, <code>h(p) == h(q)</code> must become <code>true</code> if <code>p</code> and
<code>q</code> share ownership.
</p>





</body>
</html>
