<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 758: shared_ptr and nullptr</title>
<meta property="og:title" content="Issue 758: shared_ptr and nullptr">
<meta property="og:description" content="C++ library issue. Status: C++11">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue758.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++11">C++11</a> status.</em></p>
<h3 id="758"><a href="lwg-defects.html#758">758</a>. <code>shared_ptr</code> and <code>nullptr</code></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#C++11">C++11</a>
 <b>Submitter:</b> Joe Gottman <b>Opened:</b> 2007-10-31 <b>Last modified:</b> 2016-01-28</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#C++11">C++11</a> status.</p>
<p><b>Discussion:</b></p>
<p>
Consider the following program:
</p>

<blockquote><pre>
int main() {
   shared_ptr&lt;int&gt; p(nullptr); 
   return 0;
}
</pre></blockquote>

<p>
This program will fail to compile because <code>shared_ptr</code> uses the following 
template constructor to construct itself from pointers:
</p>

<blockquote><pre>
template &lt;class Y&gt; shared_ptr(Y *);
</pre></blockquote>

<p>
According
to <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2431.pdf">N2431</a>,
the conversion from <code>nullptr_t</code> to <code>Y *</code> is not
deducible, so the above constructor will not be found.  There are similar problems with the
constructors that take a pointer and a <code>deleter</code> or a
pointer, a <code>deleter</code> and an allocator, as well as the
corresponding forms of <code>reset()</code>. Note that <a
href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2435.htm">N2435</a>
will solve this problem for constructing from just <code>nullptr</code>, but not for constructors that use
<code>deleters</code> or allocators or for <code>reset()</code>.
</p>

<p>
In the case of the functions that take deleters, there is the additional
question of what argument should be passed to the deleter when it is
eventually called.  There are two reasonable possibilities: <code>nullptr</code> or
<code>static_cast&lt;T *&gt;(0)</code>, where <code>T</code> is the template argument of the
<code>shared_ptr</code>.  It is not immediately clear which of these is better.  If
<code>D::operator()</code> is a template function similar to <code>shared_ptr</code>'s
constructor, then <code>d(static_cast&lt;T*&gt;(0))</code> will compile and <code>d(nullptr)</code>
will not.  On the other hand, if <code>D::operator()()</code> takes a parameter that
is a pointer to some type other that <code>T</code> (for instance <code>U*</code> where <code>U</code> derives
from <code>T</code>) then <code>d(nullptr)</code> will compile and <code>d(static_cast&lt;T *&gt;(0))</code> may not.
</p>

<p><i>[
Bellevue:
]</i></p>


<blockquote>
<p>
The general idea is right, we need to be able to pass a nullptr to a
shared_ptr, but there are a few borderline editorial issues here. (For
example, the single-argument nullptr_t constructor in the class synopsis
isn't marked explicit, but it is marked explicit in the proposed wording
for 20.6.6.2.1. There is a missing empty parenthesis in the form that
takes a nullptr_t, a deleter, and an allocator.)
</p>
<p>
More seriously: this issue says that a shared_ptr constructed from a
nullptr is empty. Since "empty" is undefined, it's hard to know whether
that's right. This issue is pending on handling that term better.
</p>
<p>
Peter suggests definition of empty should be "does not own anything"
</p>
<p>
Is there an editorial issue that post-conditions should refer to get() =
nullptr, rather than get() = 0?
</p>
<p>
No strong feeling towards accept or NAD, but prefer to make a decision than leave it open.
</p>
<p>
Seems there are no technical merits between NAD and Ready, comes down to
"Do we intentially want to allow/disallow null pointers with these
functions". Staw Poll - support null pointers 5 - No null pointers 0
</p>
<p>
Move to Ready, modulo editorial comments
</p>
</blockquote>

<p><i>[
post Bellevue Peter adds:
]</i></p>


<blockquote>
<p>
The following wording changes are less intrusive:
</p>

<p>
In 20.3.2.2.2 <a href="https://wg21.link/util.smartptr.shared.const">[util.smartptr.shared.const]</a>, add:
</p>

<blockquote><pre>
shared_ptr(nullptr_t);
</pre></blockquote>

<p>
after:
</p>

<blockquote><pre>
shared_ptr();
</pre></blockquote>

<p>
(Absence of explicit intentional.)
</p>

<p>
<code>px.reset( nullptr )</code> seems a somewhat contrived way to write <code>px.reset()</code>, so
I'm not convinced of its utility.
</p>
<p>
It's similarly not clear to me whether the deleter constructors need to be
extended to take <code>nullptr</code>, but if they need to:
</p>
<p>
Add
</p>

<blockquote><pre>
template&lt;class D&gt; shared_ptr(nullptr_t p, D d);
template&lt;class D, class A&gt; shared_ptr(nullptr_t p, D d, A a);
</pre></blockquote>

<p>
after
</p>

<blockquote><pre>
template&lt;class Y, class D&gt; shared_ptr(Y* p, D d);
template&lt;class Y, class D, class A&gt; shared_ptr(Y* p, D d, A a);
</pre></blockquote>

<p>
Note that this changes the semantics of the new constructors such that they
consistently call <code>d(p)</code> instead of <code>d((T*)0)</code> when <code>p</code> is <code>nullptr</code>.
</p>
<p>
The ability to be able to pass <code>0/NULL</code> to a function that takes a <code>shared_ptr</code>
has repeatedly been requested by users, but the other additions that the
proposed resolution makes are not supported by real world demand or
motivating examples.
</p>
<p>
It might be useful to split the obvious and non-controversial <code>nullptr_t</code>
constructor into a separate issue. Waiting for "empty" to be clarified is
unnecessary; this is effectively an alias for the default constructor.
</p>
</blockquote>

<p><i>[
Sophia Antipolis:
]</i></p>


<blockquote>
<p>
We want to remove the reset functions from the proposed resolution.
</p>
<p>
The remaining proposed resolution text (addressing the constructors) are wanted.
</p>
<p>
Disposition: move to review. The review should check the wording in the then-current working draft.
</p>
</blockquote>



<p id="res-758"><b>Proposed resolution:</b></p>
<p>
In 20.3.2.2 <a href="https://wg21.link/util.smartptr.shared">[util.smartptr.shared]</a> p4, add to the definition/synopsis
of <code>shared_ptr</code>:
</p>

<blockquote><pre>
template&lt;class D&gt; shared_ptr(nullptr_t p, D d);
template&lt;class D, class A&gt; shared_ptr(nullptr_t p, D d, A a);
</pre></blockquote>

<p>
after
</p>

<blockquote><pre>
template&lt;class Y, class D&gt; shared_ptr(Y* p, D d);
template&lt;class Y, class D, class A&gt; shared_ptr(Y* p, D d, A a);
</pre></blockquote>

<p>
In 20.3.2.2.2 <a href="https://wg21.link/util.smartptr.shared.const">[util.smartptr.shared.const]</a> add:
</p>

<blockquote><pre>
template&lt;class D&gt; shared_ptr(nullptr_t p, D d);
template&lt;class D, class A&gt; shared_ptr(nullptr_t p, D d, A a);
</pre></blockquote>

<p>
after
</p>

<blockquote><pre>
template&lt;class Y, class D&gt; shared_ptr(Y* p, D d);
template&lt;class Y, class D, class A&gt; shared_ptr(Y* p, D d, A a);
</pre></blockquote>

<p>
(reusing the following paragraphs 20.3.2.2.2 <a href="https://wg21.link/util.smartptr.shared.const">[util.smartptr.shared.const]</a>/9-13 that speak of p.)
</p>

<p>
In 20.3.2.2.2 <a href="https://wg21.link/util.smartptr.shared.const">[util.smartptr.shared.const]</a>/10,  change
</p>

<blockquote><p>
<i>Effects:</i> Constructs a <code>shared_ptr</code> object that <i>owns</i> the
<del>pointer</del> <ins>object</ins> <code>p</code> and the deleter <code>d</code>. The second 
constructor shall use a copy of <code>a</code> to allocate memory for internal use.
</p></blockquote>


<p><b>Rationale:</b></p>
<p><i>[
San Francisco:
]</i></p>


<blockquote><p>
"pointer" is changed to "object" to handle the fact that <code>nullptr_t</code> isn't a pointer.
</p></blockquote>






</body>
</html>
