|
| 1 | +<?xml version='1.0' encoding='utf-8' standalone='no'?> |
| 2 | +<!DOCTYPE issue SYSTEM "lwg-issue.dtd"> |
| 3 | + |
| 4 | +<issue num="4144" status="New"> |
| 5 | +<title>Disallow <code>unique_ptr<T&, D></code></title> |
| 6 | +<section><sref ref="[unique.ptr.single.general]"/></section> |
| 7 | +<submitter>Jonathan Wakely</submitter> |
| 8 | +<date>30 Aug 2024</date> |
| 9 | +<priority>99</priority> |
| 10 | + |
| 11 | +<discussion> |
| 12 | +<p> |
| 13 | +It seems that we currently allow nonsensical specializations of `unique_ptr` |
| 14 | +such as <code>unique_ptr<int&, D></code> |
| 15 | +and <code>unique_ptr<void()const, D></code> |
| 16 | +(a custom deleter that defines `D::pointer` is needed, because otherwise |
| 17 | +the `pointer` type would default to invalid types like |
| 18 | +<code>int&*</code> or <code>void(*)()const</code>). |
| 19 | +There seems to be no reason to support these "unique pointer to reference" |
| 20 | +and "unique pointer to abominable function type" specializations, |
| 21 | +or any specialization for a type that you couldn't form a raw pointer to. |
| 22 | +</p> |
| 23 | + |
| 24 | +<p> |
| 25 | +Prior to C++17, the major library implementations rejected such specializations |
| 26 | +as a side effect of the constraints for the |
| 27 | +<code>unique_ptr(auto_ptr<U>&&)</code> constructor |
| 28 | +being defined in terms of <code>is_convertible<U*, T*></code>. |
| 29 | +This meant that overload resolution for any constructor of `unique_ptr` |
| 30 | +would attempt to form the type `T*` and fail if that was invalid. |
| 31 | +With the removal of `auto_ptr` in C++17, that constructor was removed |
| 32 | +and now <code>unique_ptr<int&, D></code> can be instantiated |
| 33 | +(assuming any zombie definition of `auto_ptr` is not enabled by the library). |
| 34 | +This wasn't intentional, but just an accident caused by not explicitly |
| 35 | +forbidding such types. |
| 36 | +</p> |
| 37 | + |
| 38 | +<p> |
| 39 | +Discussion on the LWG reflector led to near-unanimous support for explicitly |
| 40 | +disallowing these specializations for non-pointable types. |
| 41 | +</p> |
| 42 | +</discussion> |
| 43 | + |
| 44 | +<resolution> |
| 45 | +<p> |
| 46 | +This wording is relative to <paper num="N4988"/>. |
| 47 | +</p> |
| 48 | + |
| 49 | +<ol> |
| 50 | +<li><p>Modify <sref ref="[unique.ptr.single.general]"/> as indicated:</p> |
| 51 | +<blockquote> |
| 52 | +<p><ins>-?- |
| 53 | +A program that instantiates the definition of |
| 54 | +<code>unique_ptr<T, D></code> |
| 55 | +is ill-formed if `T*` is an invalid type. |
| 56 | +<br/> |
| 57 | +[<em>Note</em>: |
| 58 | +This prevents the intantiation of specializations such as |
| 59 | +<code>unique_ptr<T&, D></code> |
| 60 | +and <code>unique_ptr<int() const, D></code>. |
| 61 | +— <em>end note</em>] |
| 62 | +</ins> |
| 63 | +</p> |
| 64 | +<p>-1- |
| 65 | +The default type for the template parameter `D` is `default_delete`. |
| 66 | +A client-supplied template argument `D` shall be a function object type |
| 67 | +(<sref ref="[function.objects]"/>), lvalue reference to function, |
| 68 | +or lvalue reference to function object type for which, |
| 69 | +given a value `d` of type `D` and a value `ptr` of type |
| 70 | +<code>unique_ptr<T, D>::pointer</code>, |
| 71 | +the expression `d(ptr)` is valid and has the effect of disposing of the pointer |
| 72 | +as appropriate for that deleter. |
| 73 | +</p> |
| 74 | +<p>-2- |
| 75 | +If the deleter’s type `D` is not a reference type, |
| 76 | +`D` shall meet the <em>Cpp17Destructible</em> requirements (Table 35). |
| 77 | +</p> |
| 78 | +<p>-3- |
| 79 | +If the <i>qualified-id</i> <code>remove_reference_t<D>::pointer</code> |
| 80 | +is valid and denotes a type (<sref ref="[temp.deduct]"/>), |
| 81 | +then <code>unique_ptr<T, D>::pointer</code> |
| 82 | +shall be a synonym for <code>remove_reference_t<D>::pointer</code>. |
| 83 | +Otherwise <code>unique_ptr<T, D>::pointer</code> shall be a synonym for |
| 84 | +<code>element_type*</code>. |
| 85 | +The type <code>unique_ptr<T, D>::pointer</code> shall meet the |
| 86 | +<em>Cpp17NullablePointer</em> requirements (Table 36). |
| 87 | +</p> |
| 88 | +<p>-4- |
| 89 | +[<em>Example 1</em>: |
| 90 | + Given an allocator type `X` (<sref ref="[allocator.requirements.general]"/>) |
| 91 | +and letting `A` be a synonym for <code>allocator_traits<X></code>, |
| 92 | +the types `A::pointer`, `A::const_pointer`, `A::void_pointer`, |
| 93 | +and `A::const_void_pointer` may be used as |
| 94 | +<code>unique_ptr<T, D>::pointer</code>. |
| 95 | +— <em>end example</em>] |
| 96 | +</p> |
| 97 | +</blockquote> |
| 98 | +</li> |
| 99 | +</ol> |
| 100 | +</resolution> |
| 101 | + |
| 102 | +</issue> |
0 commit comments