Topic: Using shared_ptr/weak_ptr as Keys in Unordered


Author: "'Daryl Haresign' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Wed, 9 Aug 2017 16:39:28 -0700 (PDT)
Raw View
------=_Part_287_712966165.1502321968199
Content-Type: multipart/alternative;
 boundary="----=_Part_288_43402345.1502321968200"

------=_Part_288_43402345.1502321968200
Content-Type: text/plain; charset="UTF-8"

Using shared_ptr/weak_ptr as Keys in Unordered Associative Containers

I recently had a desire to store a collection of weak_ptr objects.  As I
had no requirements on the ordering, unordered_set seemed like a natural
choice.

As it turns out, I had to use set as the required plumbing for the
unordered associative containers is not present.

I therefore propose that the required plumbing is added.

Ordered Associative Containers

Ordered associative containers require a Compare.  For shared_ptr and
weak_ptr this is provided through the owner_less function object, which
delegates to the owner_before member function.  Typical implementations of
this member involve comparing the address of the control blocks.

Unordered Associative Containers

Unordered containers require a Hash and a KeyEqual.  It probably follows to
have these work similarly to owner_before, i.e. the Hash would hash the
control block address, and the KeyEqual would compare the control block
addresses.

To be able to provide the required plumbing, there are at least a few
options.

Option 1

The first option would be to provide at the standard library level, a
similar suite of member functions and function objects as is provided to
support ordered associative containers:

   - size_t shared_ptr::owner_hash() const noexcept;
   - bool shared_ptr::owner_equal(...) const noexcept;
   - size_t weak_ptr::owner_hash() const noexcept;
   - bool weak_ptr::owner_equal(...) const noexcept;
   - template <class T> struct owner_hash;
   - template <class T> struct owner_equal;

This would provide everything someone needs out of the box.

Option 2

The second option observes the fact that given owner_hash, one could derive
equality (and indeed ordering), based on that hash.  So it would only look
to provide:

   - size_t shared_ptr::owner_hash() const noexcept;
   - size_t weak_ptr::owner_hash() const noexcept;
   - template <class T> struct owner_hash;

This would require someone to provide their own equality function object
which compares the result of calling 'owner_hash()'.

Option 3

Option 3, suggested by my colleague Masud Rahman, is similar in premise to
option 2, and would instead provide at the standard library level the bare
minimum required:

   - const void * shared_ptr::control_block() const noexcept;
   - const void * weak_ptr::control_block() const noexcept;

This would require someone to provide both a hash function object and an
equality function object.

Please let me know what you think of the idea in general, and the options
proposed below.  If I missed anything, I'm all ears.

Thanks,
Daryl.

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/90a38f4b-428b-42bd-ba36-f6dab94b7bc9%40isocpp.org.

------=_Part_288_43402345.1502321968200
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div><font size=3D"4">Using <font face=3D"courier new, mon=
ospace">shared_ptr</font>/<font face=3D"courier new, monospace">weak_ptr</f=
ont> as Keys in Unordered Associative Containers</font></div><div><br></div=
><div>I recently had a desire to store a collection of <font face=3D"courie=
r new, monospace">weak_ptr</font> objects. =C2=A0As I had no requirements o=
n the ordering, <font face=3D"courier new, monospace">unordered_set</font>=
=C2=A0seemed like a natural choice.</div><div><br></div><div>As it turns ou=
t, I had to use <font face=3D"courier new, monospace">set</font>=C2=A0as th=
e required plumbing for the unordered associative containers is not present=
..</div><div><br></div><div>I therefore propose that the required plumbing i=
s added.</div><div><br></div><div><font size=3D"4">Ordered Associative Cont=
ainers</font></div><div><br></div><div>Ordered associative containers requi=
re a <font face=3D"courier new, monospace">Compare</font>. =C2=A0For <font =
face=3D"courier new, monospace">shared_ptr</font>=C2=A0and <font face=3D"co=
urier new, monospace">weak_ptr</font> this is provided through the <font fa=
ce=3D"courier new, monospace">owner_less</font>=C2=A0function object, which=
 delegates to the <font face=3D"courier new, monospace">owner_before</font>=
=C2=A0member function. =C2=A0Typical implementations of this member involve=
 comparing the address of the control blocks.</div><div><br></div><div><fon=
t size=3D"4">Unordered Associative Containers</font></div><div><br></div><d=
iv>Unordered containers require a <font face=3D"courier new, monospace">Has=
h</font>=C2=A0and a <font face=3D"courier new, monospace">KeyEqual</font>. =
=C2=A0It probably follows to have these work similarly to <font face=3D"cou=
rier new, monospace">owner_before</font>, i.e. the <font face=3D"courier ne=
w, monospace">Hash</font>=C2=A0would hash the control block address, and th=
e <font face=3D"courier new, monospace">KeyEqual</font>=C2=A0would compare =
the control block addresses.</div><div><br></div><div>To be able to provide=
 the required plumbing, there are at least a few options.</div><div><br></d=
iv><div><font size=3D"4">Option 1</font></div><div><br></div><div>The first=
 option would be to provide at the standard library level, a similar suite =
of member functions and function objects as is provided to support ordered =
associative containers:</div><div><ul><li><font face=3D"courier new, monosp=
ace">size_t shared_ptr::owner_hash() const noexcept;</font></li><li><font f=
ace=3D"courier new, monospace">bool shared_ptr::owner_equal(...) const noex=
cept;</font></li><li><font face=3D"courier new, monospace">size_t weak_ptr:=
:owner_hash() const noexcept;</font></li><li><font face=3D"courier new, mon=
ospace">bool weak_ptr::owner_equal(...) const noexcept;</font></li><li><fon=
t face=3D"courier new, monospace">template &lt;class T&gt; struct owner_has=
h;</font></li><li><font face=3D"courier new, monospace">template &lt;class =
T&gt; struct owner_equal;</font></li></ul></div><div>This would provide eve=
rything someone needs out of the box.</div><div><br></div><div><font size=
=3D"4">Option 2</font></div><div><br></div><div>The second option observes =
the fact that given <font face=3D"courier new, monospace">owner_hash</font>=
, one could derive equality (and indeed ordering), based on that hash. =C2=
=A0So it would only look to provide:</div><div><ul><li><font face=3D"courie=
r new, monospace">size_t shared_ptr::owner_hash() const noexcept;<br></font=
></li><li><font face=3D"courier new, monospace">size_t weak_ptr::owner_hash=
() const noexcept;<br></font></li><li><font face=3D"courier new, monospace"=
>template &lt;class T&gt; struct owner_hash;</font></li></ul></div><div>Thi=
s would require someone to provide their own equality function object which=
 compares the result of calling &#39;owner_hash()&#39;.</div><div><br></div=
><div><font size=3D"4">Option 3</font></div><div><br></div><div>Option 3, s=
uggested by my colleague Masud Rahman, is similar in premise to option 2, a=
nd would instead provide at the standard library level the bare minimum req=
uired:</div><div><ul><li><font face=3D"courier new, monospace">const void *=
 shared_ptr::control_block() const noexcept;<br></font></li><li><font face=
=3D"courier new, monospace">const void * weak_ptr::control_block() const no=
except;</font></li></ul></div><div>This would require someone to provide bo=
th a hash function object and an equality function object.</div><div><br></=
div><div>Please let me know what you think of the idea in general, and the =
options proposed below. =C2=A0If I missed anything, I&#39;m all ears.</div>=
<div><br></div><div>Thanks,</div><div>Daryl.</div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/90a38f4b-428b-42bd-ba36-f6dab94b7bc9%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/90a38f4b-428b-42bd-ba36-f6dab94b7bc9=
%40isocpp.org</a>.<br />

------=_Part_288_43402345.1502321968200--

------=_Part_287_712966165.1502321968199--

.