<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 1401: Provide support for unique_ptr&lt;T&gt; == nullptr</title>
<meta property="og:title" content="Issue 1401: Provide support for unique_ptr&lt;T&gt; == nullptr">
<meta property="og:description" content="C++ library issue. Status: C++11">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue1401.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="1401"><a href="lwg-defects.html#1401">1401</a>. Provide support for <code>unique_ptr&lt;T&gt; == nullptr</code></h3>
<p><b>Section:</b> 20.2 <a href="https://wg21.link/memory">[memory]</a> <b>Status:</b> <a href="lwg-active.html#C++11">C++11</a>
 <b>Submitter:</b> BSI <b>Opened:</b> 2010-08-25 <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#memory">issues</a> in [memory].</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><b>Addresses GB-99</b></p>
<p>
One reason that the <code>unique_ptr</code> constructor taking a
<code>nullptr_t</code> argument is not <code>explicit</code> is to allow conversion
of <code>nullptr</code> to <code>unique_ptr</code> in contexts like equality
comparison. Unfortunately <code>operator==</code> for <code>unique_ptr</code> is a
little more clever than that, deducing template parameters for both
arguments. This means that <code>nullptr</code> does not get deduced
as <code>unique_ptr</code> type, and there are no other comparison
functions to match.
</p>

<p><i>[
Resolution proposed by ballot comment:
]</i></p>

<blockquote><p>
Add the following signatures to 20.2 <a href="https://wg21.link/memory">[memory]</a> p.1, <code>&lt;memory&gt;</code>
header synopsis:
</p><blockquote><pre>
template&lt;typename T, typename D&gt;
bool operator==(const unique_ptr&lt;T, D&gt; &amp; lhs, nullptr_t);
template&lt;typename T, typename D&gt;
bool operator==(nullptr_t, const unique_ptr&lt;T, D&gt; &amp; rhs);
template&lt;typename T, typename D&gt;
bool operator!=(const unique_ptr&lt;T, D&gt; &amp; lhs, nullptr_t);
template&lt;typename T, typename D&gt;
bool operator!=(nullptr_t, const unique_ptr&lt;T, D&gt; &amp; rhs);
</pre></blockquote>
</blockquote>

<p><i>[
2010-11-02 Daniel comments and provides a proposed resolution:
]</i></p>


<blockquote><p>
The same problem applies to <code>shared_ptr</code> as well: In both cases there are no
conversions considered because the comparison functions are templates. I agree with
the direction of the proposed resolution, but I believe it would be very surprising
and inconsistent, if given a smart pointer object <code>p</code>, the expression
<code>p == nullptr</code> would be provided, but not <code>p &lt; nullptr</code> and the
other relational operators. According to 7.6.9 <a href="https://wg21.link/expr.rel">[expr.rel]</a> they are defined
if null pointer values meet other pointer values, even though the result is unspecified
for all except some trivial ones. But null pointer values are nothing special here: 
The Library already defines the relational operators for both <code>unique_ptr</code> and 
<code>shared_ptr</code> and the outcome of comparing non-null pointer values will be equally 
unspecified. If the idea of supporting <code>nullptr_t</code> arguments for relational
operators is not what the committee prefers, I suggest at least to consider to remove 
the existing relational operators for both <code>unique_ptr</code> and <code>shared_ptr</code>
for consistency. But that would not be my preferred resolution of this issue.
<p/>
The number of overloads triple the current number, but I think it is much clearer to 
provide them explicitly instead of adding wording that attempts to say that "sufficient overloads" are
provided. The following proposal makes the declarations explicit.
<p/>
Additionally, the proposal adds the missing declarations for some <code>shared_ptr</code>
comparison functions for consistency.
</p></blockquote>

<p><i>[
2010-11-03 Daniel adds:
]</i></p>


<p>
Issue <a href="lwg-defects.html#1297" title="unique_ptr's relational operator functions should induce a total order (Status: Resolved)">1297</a><sup><a href="https://cplusplus.github.io/LWG/issue1297" title="Latest snapshot">(i)</a></sup> is remotely related. The following proposed resolution splits
<a href="#1401_extra_bullet">this bullet</a> into sub-bullets A and B. Sub-bullet A would 
also solve <a href="lwg-defects.html#1297" title="unique_ptr's relational operator functions should induce a total order (Status: Resolved)">1297</a><sup><a href="https://cplusplus.github.io/LWG/issue1297" title="Latest snapshot">(i)</a></sup>, but sub-bullet B would not.
<p/>
A further remark in regard to the proposed semantics of the ordering of <code>nullptr</code>
against other pointer(-like) values: One might think that the following definition might
be superior because of simplicity:
</p>
<blockquote><pre>
template&lt;class T&gt;
bool operator&lt;(const shared_ptr&lt;T&gt;&amp; a, nullptr_t);
template&lt;class T&gt;
bool operator&gt;(nullptr_t, const shared_ptr&lt;T&gt;&amp; a);
</pre><blockquote><p>
<i>Returns</i>: <code>false</code>.
</p></blockquote></blockquote>
<p>
The underlying idea behind this approach is the assumption that nullptr corresponds
to the least ordinal pointer value. But this assertion does not hold for all supported
architectures, therefore this approach was not followed because it would lead to
the inconsistency, that the following assertion could fire: 
</p>
<blockquote><pre>
shared_ptr&lt;int&gt; p(new int);
shared_ptr&lt;int&gt; null;
bool v1 = p &lt; nullptr;
bool v2 = p &lt; null;
assert(v1 == v2);
</pre></blockquote>

<p><i>[2011-03-06: Daniel comments]</i></p>


<p>The current issue state is not acceptable, because the Batavia meeting
did not give advice whether choice A or B of bullet 3 should be applied.
Option B will now be removed and if this resolution is accepted, issue
<a href="lwg-defects.html#1297" title="unique_ptr's relational operator functions should induce a total order (Status: Resolved)">1297</a><sup><a href="https://cplusplus.github.io/LWG/issue1297" title="Latest snapshot">(i)</a></sup> should be declared as resolved by <a href="lwg-defects.html#1401" title="Provide support for unique_ptr&lt;T&gt; == nullptr (Status: C++11)">1401</a><sup><a href="https://cplusplus.github.io/LWG/issue1401" title="Latest snapshot">(i)</a></sup>.
This update also resyncs the wording with N3242.</p>



<p id="res-1401"><b>Proposed resolution:</b></p>
<p>
Wording changes are against N3242.
</p>
<ol>
<li>Change 20.2.2 <a href="https://wg21.link/memory.syn">[memory.syn]</a> p. 1, header <code>&lt;memory&gt;</code> synopsis as indicated.
<code>noexcept</code> specifications are only added, where the guarantee exists, that the function
shall no throw an exception (as replacement of &quot;<i>Throws</i>: Nothing&quot;. Note that
the <code>noexcept</code> additions to the <code>shared_ptr</code> comparisons are editorial, because
they are already part of the accepted paper <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3195.htm">n3195</a>:
<blockquote><pre>
namespace std {
  [&hellip;]
  // <i>[unique.ptr] Class unique_ptr:</i>
  template &lt;class T&gt; class default_delete;
  template &lt;class T&gt; class default_delete&lt;T[]&gt;;
  template &lt;class T, class D = default_delete&lt;T&gt;&gt; class unique_ptr;
  template &lt;class T, class D&gt; class unique_ptr&lt;T[], D&gt;;

  template &lt;class T1, class D1, class T2, class D2&gt;
  bool operator==(const unique_ptr&lt;T1, D1&gt;&amp; x, const unique_ptr&lt;T2, D2&gt;&amp; y);
  template &lt;class T1, class D1, class T2, class D2&gt;
  bool operator!=(const unique_ptr&lt;T1, D1&gt;&amp; x, const unique_ptr&lt;T2, D2&gt;&amp; y);
  template &lt;class T1, class D1, class T2, class D2&gt;
  bool operator&lt;(const unique_ptr&lt;T1, D1&gt;&amp; x, const unique_ptr&lt;T2, D2&gt;&amp; y);
  template &lt;class T1, class D1, class T2, class D2&gt;
  bool operator&lt;=(const unique_ptr&lt;T1, D1&gt;&amp; x, const unique_ptr&lt;T2, D2&gt;&amp; y);
  template &lt;class T1, class D1, class T2, class D2&gt;
  bool operator&gt;(const unique_ptr&lt;T1, D1&gt;&amp; x, const unique_ptr&lt;T2, D2&gt;&amp; y);
  template &lt;class T1, class D1, class T2, class D2&gt;
  bool operator&gt;=(const unique_ptr&lt;T1, D1&gt;&amp; x, const unique_ptr&lt;T2, D2&gt;&amp; y);

  <ins>template &lt;class T, class D&gt;</ins>
  <ins>bool operator==(const unique_ptr&lt;T, D&gt;&amp; x, nullptr_t) noexcept;</ins>
  <ins>template &lt;class T, class D&gt;</ins>
  <ins>bool operator==(nullptr_t, const unique_ptr&lt;T, D&gt;&amp; x) noexcept;</ins>
  <ins>template &lt;class T, class D&gt;</ins>
  <ins>bool operator!=(const unique_ptr&lt;T, D&gt;&amp; x, nullptr_t) noexcept;</ins>
  <ins>template &lt;class T, class D&gt;</ins>
  <ins>bool operator!=(nullptr_t, const unique_ptr&lt;T, D&gt;&amp; x) noexcept;</ins>
  <ins>template &lt;class T, class D&gt;</ins>
  <ins>bool operator&lt;(const unique_ptr&lt;T, D&gt;&amp; x, nullptr_t);</ins>
  <ins>template &lt;class T, class D&gt;</ins>
  <ins>bool operator&lt;(nullptr_t, const unique_ptr&lt;T, D&gt;&amp; x);</ins>
  <ins>template &lt;class T, class D&gt;</ins>
  <ins>bool operator&lt;=(const unique_ptr&lt;T, D&gt;&amp; x, nullptr_t);</ins>
  <ins>template &lt;class T, class D&gt;</ins>
  <ins>bool operator&lt;=(nullptr_t, const unique_ptr&lt;T, D&gt;&amp; x);</ins>
  <ins>template &lt;class T, class D&gt;</ins>
  <ins>bool operator&gt;(const unique_ptr&lt;T, D&gt;&amp; x, nullptr_t);</ins>
  <ins>template &lt;class T, class D&gt;</ins>
  <ins>bool operator&gt;(nullptr_t, const unique_ptr&lt;T, D&gt;&amp; x);</ins>
  <ins>template &lt;class T, class D&gt;</ins>
  <ins>bool operator&gt;=(const unique_ptr&lt;T, D&gt;&amp; x, nullptr_t);</ins>
  <ins>template &lt;class T, class D&gt;</ins>
  <ins>bool operator&gt;=(nullptr_t, const unique_ptr&lt;T, D&gt;&amp; x);</ins>
  
  // <i>[util.smartptr.weakptr], Class bad_weak_ptr:</i>
  class bad_weak_ptr;

  // <i>[util.smartptr.shared], Class template shared_ptr:</i>
  template&lt;class T&gt; class shared_ptr;

  // <i>[util.smartptr.shared.cmp], shared_ptr comparisons:</i>
  template&lt;class T, class U&gt;
  bool operator==(shared_ptr&lt;T&gt; const&amp; a, shared_ptr&lt;U&gt; const&amp; b) <ins> noexcept</ins>;
  template&lt;class T, class U&gt;
  bool operator!=(shared_ptr&lt;T&gt; const&amp; a, shared_ptr&lt;U&gt; const&amp; b) <ins> noexcept</ins>;
  template&lt;class T, class U&gt;
  bool operator&lt;(shared_ptr&lt;T&gt; const&amp; a, shared_ptr&lt;U&gt; const&amp; b) <ins> noexcept</ins>;
  template&lt;class T, class U&gt;
  bool operator&gt;(shared_ptr&lt;T&gt; const&amp; a, shared_ptr&lt;U&gt; const&amp; b) <ins> noexcept</ins>;
  template&lt;class T, class U&gt;
  bool operator&lt;=(shared_ptr&lt;T&gt; const&amp; a, shared_ptr&lt;U&gt; const&amp; b) <ins> noexcept</ins>;
  template&lt;class T, class U&gt;
  bool operator&gt;=(shared_ptr&lt;T&gt; const&amp; a, shared_ptr&lt;U&gt; const&amp; b) <ins> noexcept</ins>;

  <ins>template&lt;class T&gt;</ins>
  <ins>bool operator==(shared_ptr&lt;T&gt; const&amp; a, nullptr_t) noexcept;</ins>
  <ins>template&lt;class T&gt;</ins>
  <ins>bool operator==(nullptr_t, shared_ptr&lt;T&gt; const&amp; a) noexcept;</ins>
  <ins>template&lt;class T&gt;</ins>
  <ins>bool operator!=(shared_ptr&lt;T&gt; const&amp; a, nullptr_t) noexcept;</ins>
  <ins>template&lt;class T&gt;</ins>
  <ins>bool operator!=(nullptr_t, shared_ptr&lt;T&gt; const&amp; a) noexcept;</ins>
  <ins>template&lt;class T&gt;</ins>
  <ins>bool operator&lt;(shared_ptr&lt;T&gt; const&amp; a, nullptr_t) noexcept;</ins>
  <ins>template&lt;class T&gt;</ins>
  <ins>bool operator&lt;(nullptr_t, shared_ptr&lt;T&gt; const&amp; a) noexcept;</ins>
  <ins>template&gt;class T&gt;</ins>
  <ins>bool operator&gt;(shared_ptr&lt;T&gt; const&amp; a, nullptr_t) noexcept;</ins>
  <ins>template&gt;class T&gt;</ins>
  <ins>bool operator&gt;(nullptr_t, shared_ptr&lt;T&gt; const&amp; a) noexcept;</ins>
  <ins>template&lt;class T&gt;</ins>
  <ins>bool operator&lt;=(shared_ptr&lt;T&gt; const&amp; a, nullptr_t) noexcept;</ins>
  <ins>template&lt;class T&gt;</ins>
  <ins>bool operator&lt;=(nullptr_t, shared_ptr&lt;T&gt; const&amp; a) noexcept;</ins>
  <ins>template&gt;class T&gt;</ins>
  <ins>bool operator&gt;=(shared_ptr&lt;T&gt; const&amp; a, nullptr_t) noexcept;</ins>
  <ins>template&gt;class T&gt;</ins>
  <ins>bool operator&gt;=(nullptr_t, shared_ptr&lt;T&gt; const&amp; a) noexcept;</ins>

  [&hellip;]
}
</pre></blockquote>
</li>
<li>Change the synopsis just after 20.3.1 <a href="https://wg21.link/unique.ptr">[unique.ptr]</a> p. 6 as indicated:
<blockquote><pre>
namespace std {
  [&hellip;]
  
  template &lt;class T1, class D1, class T2, class D2&gt;
  bool operator==(const unique_ptr&lt;T1, D1&gt;&amp; x, const unique_ptr&lt;T2, D2&gt;&amp; y);
  template &lt;class T1, class D1, class T2, class D2&gt;
  bool operator!=(const unique_ptr&lt;T1, D1&gt;&amp; x, const unique_ptr&lt;T2, D2&gt;&amp; y);
  template &lt;class T1, class D1, class T2, class D2&gt;
  bool operator&lt;(const unique_ptr&lt;T1, D1&gt;&amp; x, const unique_ptr&lt;T2, D2&gt;&amp; y);
  template &lt;class T1, class D1, class T2, class D2&gt;
  bool operator&lt;=(const unique_ptr&lt;T1, D1&gt;&amp; x, const unique_ptr&lt;T2, D2&gt;&amp; y);
  template &lt;class T1, class D1, class T2, class D2&gt;
  bool operator&gt;(const unique_ptr&lt;T1, D1&gt;&amp; x, const unique_ptr&lt;T2, D2&gt;&amp; y);
  template &lt;class T1, class D1, class T2, class D2&gt;
  bool operator&gt;=(const unique_ptr&lt;T1, D1&gt;&amp; x, const unique_ptr&lt;T2, D2&gt;&amp; y);

  <ins>template &lt;class T, class D&gt;</ins>
  <ins>bool operator==(const unique_ptr&lt;T, D&gt;&amp; x, nullptr_t) noexcept;</ins>
  <ins>template &lt;class T, class D&gt;</ins>
  <ins>bool operator==(nullptr_t, const unique_ptr&lt;T, D&gt;&amp; x) noexcept;</ins>
  <ins>template &lt;class T, class D&gt;</ins>
  <ins>bool operator!=(const unique_ptr&lt;T, D&gt;&amp; x, nullptr_t) noexcept;</ins>
  <ins>template &lt;class T, class D&gt;</ins>
  <ins>bool operator!=(nullptr_t, const unique_ptr&lt;T, D&gt;&amp; x) noexcept;</ins>
  <ins>template &lt;class T, class D&gt;</ins>
  <ins>bool operator&lt;(const unique_ptr&lt;T, D&gt;&amp; x, nullptr_t);</ins>
  <ins>template &lt;class T, class D&gt;</ins>
  <ins>bool operator&lt;(nullptr_t, const unique_ptr&lt;T, D&gt;&amp; x);</ins>
  <ins>template &lt;class T, class D&gt;</ins>
  <ins>bool operator&lt;=(const unique_ptr&lt;T, D&gt;&amp; x, nullptr_t);</ins>
  <ins>template &lt;class T, class D&gt;</ins>
  <ins>bool operator&lt;=(nullptr_t, const unique_ptr&lt;T, D&gt;&amp; x);</ins>
  <ins>template &lt;class T, class D&gt;</ins>
  <ins>bool operator&gt;(const unique_ptr&lt;T, D&gt;&amp; x, nullptr_t);</ins>
  <ins>template &lt;class T, class D&gt;</ins>
  <ins>bool operator&gt;(nullptr_t, const unique_ptr&lt;T, D&gt;&amp; x);</ins>
  <ins>template &lt;class T, class D&gt;</ins>
  <ins>bool operator&gt;=(const unique_ptr&lt;T, D&gt;&amp; x, nullptr_t);</ins>
  <ins>template &lt;class T, class D&gt;</ins>
  <ins>bool operator&gt;=(nullptr_t, const unique_ptr&lt;T, D&gt;&amp; x);</ins>

}
</pre></blockquote>
</li>
<li><a name="1401_extra_bullet">This bullet does now only suggest the first approach:</a>
<p>Change 20.3.1.6 <a href="https://wg21.link/unique.ptr.special">[unique.ptr.special]</a> p. 4-7 as indicated and add a series of prototype
descriptions:</p>
<blockquote><pre>
template &lt;class T1, class D1, class T2, class D2&gt;
  bool operator&lt;(const unique_ptr&lt;T1, D1&gt;&amp; x, const unique_ptr&lt;T2, D2&gt;&amp; y);
</pre>

<blockquote>
<p>
<ins>? <i>Requires:</i> Let <code>CT</code> be <code>common_type&lt;unique_ptr&lt;T1,
D1&gt;::pointer, unique_ptr&lt;T2, D2&gt;::pointer&gt;::type</code>. Then
the specialization <code>less&lt;CT&gt;</code> shall be a function object type ([function.objects]) 
that induces a strict weak ordering ([alg.sorting]) on the pointer values.</ins>
</p>

<p>
4 <i>Returns:</i> <code><ins>less&lt;CT&gt;()(x.get(), y.get())</ins><del>x.get()
&lt; y.get()</del></code>.
</p>

<p>
<ins>? <i>Remarks:</i> If <code>unique_ptr&lt;T1, D1&gt;::pointer</code> is not
implicitly convertible to <code>CT</code> or <code>unique_ptr&lt;T2,
D2&gt;::pointer</code> is not implicitly convertible to <code>CT</code>, the program
is ill-formed.</ins>
</p>
</blockquote>

<pre>
template &lt;class T1, class D1, class T2, class D2&gt;
  bool operator&lt;=(const unique_ptr&lt;T1, D1&gt;&amp; x, const unique_ptr&lt;T2, D2&gt;&amp; y);
</pre>

<blockquote><p>
5 <i>Returns:</i> <code><ins>!(y &lt; x)</ins><del>x.get() &lt;= y.get()</del></code>.
</p></blockquote>

<pre>
template &lt;class T1, class D1, class T2, class D2&gt;
  bool operator&gt;(const unique_ptr&lt;T1, D1&gt;&amp; x, const unique_ptr&lt;T2, D2&gt;&amp; y);
</pre>

<blockquote><p>
6 <i>Returns:</i> <code><ins>(y &lt; x)</ins><del>x.get() &gt; y.get()</del></code>.
</p></blockquote>

<pre>
template &lt;class T1, class D1, class T2, class D2&gt;
  bool operator&gt;=(const unique_ptr&lt;T1, D1&gt;&amp; x, const unique_ptr&lt;T2, D2&gt;&amp; y);
</pre>

<blockquote><p>
7 <i>Returns:</i> <code><ins>!(x &lt; y)</ins><del>x.get() &gt;= y.get()</del></code>.
</p></blockquote>
</blockquote>

<blockquote><pre>
<ins>template &lt;class T, class D&gt;</ins>
<ins>bool operator==(const unique_ptr&lt;T, D&gt;&amp; x, nullptr_t) noexcept;</ins>
<ins>template &lt;class T, class D&gt;</ins>
<ins>bool operator==(nullptr_t, const unique_ptr&lt;T, D&gt;&amp; x) noexcept;</ins>
</pre><blockquote><p>
<ins>? <i>Returns</i>: <code>!x</code>.</ins>
</p></blockquote></blockquote>

<blockquote><pre>
<ins>template &lt;class T, class D&gt;</ins>
<ins>bool operator!=(const unique_ptr&lt;T, D&gt;&amp; x, nullptr_t) noexcept;</ins>
<ins>template &lt;class T, class D&gt;</ins>
<ins>bool operator!=(nullptr_t, const unique_ptr&lt;T, D&gt;&amp; x) noexcept;</ins>
</pre><blockquote><p>
<ins>? <i>Returns</i>: <code>(bool) x</code>.</ins>
</p></blockquote></blockquote>

<blockquote><pre>
<ins>template &lt;class T, class D&gt;</ins>
<ins>bool operator&lt;(const unique_ptr&lt;T, D&gt;&amp; x, nullptr_t);</ins>
<ins>template &lt;class T, class D&gt;</ins>
<ins>bool operator&gt;(nullptr_t, const unique_ptr&lt;T, D&gt;&amp; x);</ins>
</pre>
<blockquote><p>
<ins>? <i>Requires:</i> The specialization <code>less&lt;unique_ptr&lt;T, D&gt;::pointer&gt;</code> 
shall be a function object type ([function.objects]) that induces a strict weak ordering ([alg.sorting])
on the pointer values.</ins>
</p></blockquote>
<blockquote><p>
<ins>? <i>Returns</i>: <code>less&lt;unique_ptr&lt;T, D&gt;::pointer&gt;()(x.get(), nullptr)</code>.</ins>
</p></blockquote></blockquote>

<blockquote><pre>
<ins>template &lt;class T, class D&gt;</ins>
<ins>bool operator&lt;(nullptr_t, const unique_ptr&lt;T, D&gt;&amp; x);</ins>
<ins>template &lt;class T, class D&gt;</ins>
<ins>bool operator&gt;(const unique_ptr&lt;T, D&gt;&amp; x, nullptr_t);</ins>
</pre>
<blockquote><p>
<ins>? <i>Requires:</i> The specialization <code>less&lt;unique_ptr&lt;T, D&gt;::pointer&gt;</code> 
shall be a function object type ([function.objects]) that induces a strict weak ordering ([alg.sorting])
on the pointer values.</ins>
</p></blockquote>
<blockquote><p>
<ins>? <i>Returns</i>: <code>less&lt;unique_ptr&lt;T, D&gt;::pointer&gt;()(nullptr, x.get())</code>.</ins>
</p></blockquote></blockquote>

<blockquote><pre>
<ins>template &lt;class T, class D&gt;</ins>
<ins>bool operator&lt;=(const unique_ptr&lt;T, D&gt;&amp; x, nullptr_t);</ins>
<ins>template &lt;class T, class D&gt;</ins>
<ins>bool operator&gt;=(nullptr_t, const unique_ptr&lt;T, D&gt;&amp; x);</ins>
</pre><blockquote><p>
<ins>? <i>Returns</i>: <code>!(nullptr &lt; x)</code>.</ins>
</p></blockquote></blockquote>

<blockquote><pre>
<ins>template &lt;class T, class D&gt;</ins>
<ins>bool operator&lt;=(nullptr_t, const unique_ptr&lt;T, D&gt;&amp; x);</ins>
<ins>template &lt;class T, class D&gt;</ins>
<ins>bool operator&gt;=(const unique_ptr&lt;T, D&gt;&amp; x, nullptr_t);</ins>
</pre><blockquote><p>
<ins>? <i>Returns</i>: <code>!(x &lt; nullptr)</code>.</ins>
</p></blockquote></blockquote>


</li>
<li><p>Change 20.3.2.2 <a href="https://wg21.link/util.smartptr.shared">[util.smartptr.shared]</a> p. 1, class template <code>shared_ptr</code>
synopsis as indicated. For consistency reasons the remaining normal relation
operators are added as well:
</p>
<blockquote><pre>
namespace std {

  [&hellip;]

  // <i>[util.smartptr.shared.cmp], shared_ptr comparisons:</i>
  template&lt;class T, class U&gt;
  bool operator==(const shared_ptr&lt;T&gt;&amp; a, const shared_ptr&lt;U&gt;&amp; b) noexcept;
  template&lt;class T, class U&gt;
  bool operator!=(const shared_ptr&lt;T&gt;&amp; a, const shared_ptr&lt;U&gt;&amp; b) noexcept;
  template&lt;class T, class U&gt;
  bool operator&lt;(const shared_ptr&lt;T&gt;&amp; a, const shared_ptr&lt;U&gt;&amp; b) noexcept;
  <ins>template&lt;class T, class U&gt;</ins>
  <ins>bool operator&gt;(const shared_ptr&lt;T&gt;&amp; a, const shared_ptr&lt;U&gt;&amp; b) noexcept;</ins>
  <ins>template&lt;class T, class U&gt;</ins>
  <ins>bool operator&lt;=(const shared_ptr&lt;T&gt;&amp; a, const shared_ptr&lt;U&gt;&amp; b) noexcept;</ins>
  <ins>template&lt;class T, class U&gt;</ins>
  <ins>bool operator&gt;=(const shared_ptr&lt;T&gt;&amp; a, const shared_ptr&lt;U&gt;&amp; b) noexcept;</ins>

  <ins>template&lt;class T&gt;</ins>
  <ins>bool operator==(const shared_ptr&lt;T&gt;&amp; a, nullptr_t) noexcept;</ins>
  <ins>template&lt;class T&gt;</ins>
  <ins>bool operator==(nullptr_t, const shared_ptr&lt;T&gt;&amp; a) noexcept;</ins>
  <ins>template&lt;class T&gt;</ins>
  <ins>bool operator!=(const shared_ptr&lt;T&gt;&amp; a, nullptr_t) noexcept;</ins>
  <ins>template&lt;class T&gt;</ins>
  <ins>bool operator!=(nullptr_t, const shared_ptr&lt;T&gt;&amp; a) noexcept;</ins>
  <ins>template&lt;class T&gt;</ins>
  <ins>bool operator&lt;(const shared_ptr&lt;T&gt;&amp; a, nullptr_t) noexcept;</ins>
  <ins>template&lt;class T&gt;</ins>
  <ins>bool operator&lt;(nullptr_t, const shared_ptr&lt;T&gt;&amp; a) noexcept;</ins>
  <ins>template&gt;class T&gt;</ins>
  <ins>bool operator&gt;(const shared_ptr&lt;T&gt;&amp; a, nullptr_t) noexcept;</ins>
  <ins>template&gt;class T&gt;</ins>
  <ins>bool operator&gt;(nullptr_t, const shared_ptr&lt;T&gt;&amp; a) noexcept;</ins>
  <ins>template&lt;class T&gt;</ins>
  <ins>bool operator&lt;=(const shared_ptr&lt;T&gt;&amp; a, nullptr_t) noexcept;</ins>
  <ins>template&lt;class T&gt;</ins>
  <ins>bool operator&lt;=(nullptr_t, const shared_ptr&lt;T&gt;&amp; a) noexcept;</ins>
  <ins>template&gt;class T&gt;</ins>
  <ins>bool operator&gt;=(const shared_ptr&lt;T&gt;&amp; a, nullptr_t) noexcept;</ins>
  <ins>template&gt;class T&gt;</ins>
  <ins>bool operator&gt;=(nullptr_t, const shared_ptr&lt;T&gt;&amp; a) noexcept;</ins>

  [&hellip;]
}
</pre></blockquote>
</li>
<li>Add the following series of prototype specifications at the very end of 20.3.2.2.8 <a href="https://wg21.link/util.smartptr.shared.cmp">[util.smartptr.shared.cmp]</a>.
For mixed comparison the general &quot;generation&quot; rule of  [operators] p. 10 does not apply, 
therefore all of them are defined. Below wording takes advantage of the simplified definition of the
<em>composite pointer type</em> if one partner is a null pointer constant:
<blockquote><pre>
<ins>template&lt;class T&gt;</ins>
<ins>bool operator==(const shared_ptr&lt;T&gt;&amp; a, nullptr_t) noexcept;</ins>
<ins>template&lt;class T&gt;</ins>
<ins>bool operator==(nullptr_t, const shared_ptr&lt;T&gt;&amp; a) noexcept;</ins>
</pre><blockquote><p>
<ins>? <i>Returns</i>: <code>!a</code>.</ins>
</p></blockquote></blockquote>

<blockquote><pre>
<ins>template&lt;class T&gt;</ins>
<ins>bool operator!=(const shared_ptr&lt;T&gt;&amp; a, nullptr_t) noexcept;</ins>
<ins>template&lt;class T&gt;</ins>
<ins>bool operator!=(nullptr_t, const shared_ptr&lt;T&gt;&amp; a) noexcept;</ins>
</pre><blockquote><p>
<ins>? <i>Returns</i>: <code>(bool) a</code>.</ins>
</p></blockquote></blockquote>

<blockquote><pre>
<ins>template&lt;class T&gt;</ins>
<ins>bool operator&lt;(const shared_ptr&lt;T&gt;&amp; a, nullptr_t) noexcept;</ins>
<ins>template&lt;class T&gt;</ins>
<ins>bool operator&gt;(nullptr_t, const shared_ptr&lt;T&gt;&amp; a) noexcept;</ins>
</pre><blockquote><p>
<ins>? <i>Returns</i>: <code>less&lt;T*&gt;()(a.get(), nullptr)</code>.</ins>
</p></blockquote></blockquote>

<blockquote><pre>
<ins>template&lt;class T&gt;</ins>
<ins>bool operator&lt;(nullptr_t, const shared_ptr&lt;T&gt;&amp; a) noexcept;</ins>
<ins>template&lt;class T&gt;</ins>
<ins>bool operator&gt;(const shared_ptr&lt;T&gt;&amp; a, nullptr_t) noexcept;</ins>
</pre><blockquote><p>
<ins>? <i>Returns</i>: <code>less&lt;T*&gt;()(nullptr, a.get())</code>.</ins>
</p></blockquote></blockquote>

<blockquote><pre>
<ins>template&lt;class T&gt;</ins>
<ins>bool operator&lt;=(const shared_ptr&lt;T&gt;&amp; a, nullptr_t) noexcept;</ins>
<ins>template&lt;class T&gt;</ins>
<ins>bool operator&gt;=(nullptr_t, const shared_ptr&lt;T&gt;&amp; a) noexcept;</ins>
</pre><blockquote><p>
<ins>? <i>Returns</i>: <code>!(nullptr &lt; a)</code>.</ins>
</p></blockquote></blockquote>

<blockquote><pre>
<ins>template&lt;class T&gt;</ins>
<ins>bool operator&lt;=(nullptr_t, const shared_ptr&lt;T&gt;&amp; a) noexcept;</ins>
<ins>template&lt;class T&gt;</ins>
<ins>bool operator&gt;=(const shared_ptr&lt;T&gt;&amp; a, nullptr_t) noexcept;</ins>
</pre><blockquote><p>
<ins>? <i>Returns</i>: <code>!(a &lt; nullptr)</code>.</ins>
</p></blockquote></blockquote>

</li>
</ol>





</body>
</html>
