Skip to content

Commit c5866c6

Browse files
committed
New issue from Hewill Kang: "unique_ptr<void>::operator* is not SFINAE-friendly"
1 parent 5ce9b9a commit c5866c6

File tree

1 file changed

+81
-0
lines changed

1 file changed

+81
-0
lines changed

xml/issue4324.xml

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?xml version='1.0' encoding='utf-8' standalone='no'?>
2+
<!DOCTYPE issue SYSTEM "lwg-issue.dtd">
3+
4+
<issue num="4324" status="New">
5+
<title><code>unique_ptr&lt;void&gt;::operator*</code> is not SFINAE-friendly</title>
6+
<section>
7+
<sref ref="[unique.ptr.single.observers]"/>
8+
</section>
9+
<submitter>Hewill Kang</submitter>
10+
<date>24 Aug 2025</date>
11+
<priority>99</priority>
12+
13+
<discussion>
14+
<p>
15+
LWG <iref ref="2762"/> added a conditional `noexcept` specification to `unique_ptr::operator*`
16+
to make it consistent with `shared_ptr::operator*`:
17+
</p>
18+
<pre>
19+
constexpr add_lvalue_reference_t&lt;T&gt; operator*() const <ins>noexcept(noexcept(*declval&lt;pointer&gt;()))</ins>;
20+
</pre>
21+
<p>
22+
This unexpectedly makes <code>unique_ptr&lt;void&gt;::operator*</code> no longer SFINAE-friendly,
23+
<a href="https://godbolt.org/z/xd15jYPhz">for example</a>:
24+
</p>
25+
<blockquote><pre>
26+
#include &lt;memory&gt;
27+
28+
template&lt;class T&gt; concept dereferenceable = requires(T&amp; t) { *t; };
29+
30+
static_assert( dereferenceable&lt;int *&gt;);
31+
static_assert(!dereferenceable&lt;void*&gt;);
32+
33+
static_assert( dereferenceable&lt;std::shared_ptr&lt;int &gt;&gt;);
34+
static_assert(!dereferenceable&lt;std::shared_ptr&lt;void&gt;&gt;);
35+
36+
static_assert( dereferenceable&lt;std::unique_ptr&lt;int &gt;&gt;);
37+
static_assert( dereferenceable&lt;std::unique_ptr&lt;void&gt;&gt;); // <span style="color:#C80000;font-weight:bold">hard error</span>
38+
</pre></blockquote>
39+
<p>
40+
Given that the standard intends for `operator*` of `shared_ptr` and `unique_ptr` to be
41+
SFINAE-friendly based on <sref ref="[util.smartptr.shared.obs]"/>, regardless of the value of
42+
`static_assert`, it is reasonable to assume that there should be no hard error here.
43+
</p>
44+
</discussion>
45+
46+
<resolution>
47+
<p>
48+
This wording is relative to <paper num="N5014"/>.
49+
</p>
50+
51+
<ol>
52+
53+
<li><p>Modify <sref ref="[unique.ptr.single.observers]"/> as indicated:</p>
54+
55+
<blockquote>
56+
<pre>
57+
constexpr add_lvalue_reference_t&lt;T&gt; operator*() const noexcept(<del>noexcept(*declval&lt;pointer&gt;())</del><ins><i>see below</i></ins>);
58+
</pre>
59+
<blockquote>
60+
<p>
61+
-1- <i>Mandates</i>: <tt>reference_converts_from_temporary_v&lt;add_lvalue_reference_t&lt;T&gt;,
62+
decltype(*declval&lt;pointer&gt;())&gt;</tt> is `false`.
63+
<p/>
64+
-2- <i>Preconditions</i>: `get() != nullptr` is `true`.
65+
<p/>
66+
-3- <i>Returns</i>: `*get()`.
67+
<p/>
68+
<ins>-?- <i>Remarks:</i>: The exception specification is equivalent to:</ins>
69+
</p>
70+
<blockquote><pre>
71+
<ins>!requires { *declval&lt;pointer&gt;(); } || requires { { *declval&lt;pointer&gt;() } noexcept; }</ins>
72+
</pre></blockquote>
73+
</blockquote>
74+
</blockquote>
75+
76+
</li>
77+
78+
</ol>
79+
</resolution>
80+
81+
</issue>

0 commit comments

Comments
 (0)