﻿<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>

<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">

<style type="text/css">

body { color: #000000; background-color: #FFFFFF; }
del { text-decoration: line-through; color: #8B0040; }
ins { text-decoration: underline; color: #005100; }

p.example { margin-left: 2em; }
pre.example { margin-left: 2em; }
div.example { margin-left: 2em; }

code.extract { background-color: #F5F6A2; }
pre.extract { margin-left: 2em; background-color: #F5F6A2;
              border: 1px solid #E1E28E; }

p.function { }
.attribute { margin-left: 2em; }
.attribute dt { float: left; font-style: italic;
                padding-right: 1ex; }
.attribute dd { margin-left: 0em; }

blockquote.std { color: #000000; background-color: #F1F1F1;
                 border: 1px solid #D1D1D1;
                 padding-left: 0.5em; padding-right: 0.5em; }
blockquote.stddel { text-decoration: line-through;
                    color: #000000; background-color: #FFEBFF;
                    border: 1px solid #ECD7EC;
                    padding-left: 0.5em; padding-right: 0.5em; }

blockquote.stdins { text-decoration: underline;
                    color: #000000; background-color: #C8FFC8;
                    border: 1px solid #B3EBB3; padding: 0.5em; }

table { border: 1px solid black; border-spacing: 0px;
        margin-left: auto; margin-right: auto; }
th { text-align: left; vertical-align: top;
     padding-left: 0.8em; border: none; }
td { text-align: left; vertical-align: top;
     padding-left: 0.8em; border: none; }

p.grammarlhs { margin-bottom: 0 }
p.grammarrhs { margin-left:8em; margin-top:0; text-indent:-4em }

</style>

<title>Removing auto_ptr</title>
</head>

<body>

<div style="text-align: right; float: right">
<p>ISO/IEC JTC1 SC22 WG21<br>N4168<br><a href="mailto:billy.baker@flightsafety.com">Billy Baker</a><br>2014-10-02</p>
</div>

<h1>Removing auto_ptr</h1>

<h2>Introduction</h2>
<p>At Oxford in 2007, N1856 was accepted adding <code>unique_ptr</code> and making <code>auto_ptr</code> 
deprecated. At CppCon in 2014, Howard Hinnant stated that he would like to see <code>auto_ptr</code> removed 
from future C++ standards. This paper proposes that <code>auto_ptr</code> be removed entirely. Removing <code>auto_ptr</code> 
now would give plenty of time before the next C++ standard for code to be updated if necessary.</p>
 
<h2>Proposal</h2>

<p>The conclusion of N1856 for deprecating <code>auto_ptr</code> was:</p>

<blockquote class="std">
Conclusion:<br>

    One should not move from lvalues using copy syntax. Other syntax for moving should be used instead. Otherwise generic code is likely to initiate a move when a copy was intended.<br><br>

<code>auto_ptr</code> moves from lvalues using copy syntax and is thus fundamentally unsafe.
</blockquote>

N1856 also pointed out that one feature of <code>auto_ptr</code> was no longer valid.

<blockquote class="std">
 <code>auto_ptr</code> was originally intended to allow for easy conversions between base and derived types. However recent changes to the standard result in <code>auto_ptr&lt;Base&gt;</code> not cooperating as originally intended with <code>auto_ptr&lt;Dervied&gt;</code>:<br>
<br>
<pre>
    struct B {virtual ~B() {}};
    struct D : B {};

    auto_ptr<D>
    ap_factory()
    {
        return auto_ptr<D>();
    }

    void ap_sink(auto_ptr&lt;B&gt;);

    void test()
    {
        auto_ptr&lt;B&gt; ap = ap_factory();  // error:
                                        // no suitable copy constructor
        ap_sink(ap_factory());   // error: no suitable copy constructor
    }
</pre>
</blockquote>

In the 7 years since the adoption of N1856, the material for learning C++ has 
made it clear that <code>auto_ptr</code> should not be used.

In <i>The C++ Standard Library Second Edition</i>, Nico Josuttis lists problems with <code>auto_ptr</code>.

<blockquote class="std">
<ul>
<li>At the time of its design, the language had no move semantics for constructors and 
assignment operators. However, the goal was still to provide the semantics of ownership 
transfer. As a result, copy and assignment operators got a move semantic, which could 
cause serious trouble, especially when passing an <code>auto_ptr</code> as argument</li>
<li>There was no semantic of a <i>deleter</i>, so you could use it only to deal with single objects 
allocated with new.</li>
<li>Because this was initially the only smart pointer provided by the C++ standard library, 
it was often misused, especially assuming that it provided the semantics of <i>shared ownership</i> 
as class <code>shared_ptr</code> does now.</li>
</ul>
</blockquote>

Herb Sutter's <a href="http://herbsutter.com/2013/05/29/gotw-89-solution-smart-pointers/">GotW #89</a> on 
Smart Pointers answers the question of "What's the deal with auto_ptr?"
<blockquote class="std">
<code>auto_ptr</code> is most charitably characterized as a valiant attempt to create a <code>unique_ptr</code> 
before C++ had move semantics. <code>auto_ptr</code> is now deprecated, and should not be used in new code.<br><br>

If you have <code>auto_ptr</code> in an existing code base, when you get a chance try doing a global search-and-replace 
of <code>auto_ptr</code> to <code>unique_ptr</code>; the vast majority of uses will work the same, and it might expose 
(as a compile-time error) or fix (silently) a bug or two you didn’t know you had. 
</blockquote>

While simple find and replace would work, tools have also been developed to modernize C++ code using transformations 
such as replacing <code>auto_ptr</code> with <code>unique_ptr</code>.<p>

<h2>Proposed wording</h2>

<p>These proprosed changes are relative to N3797</p>

<p>Change in 20.7.2 (memory.syn):</p>

<blockquote class="std">
<pre>
<del>// D.10, auto_ptr (deprecated)
template <class X> class auto_ptr;</del></pre>
</blockquote>

<p>Change 20.8.1.2 (unique.ptr.single):</p>

<blockquote class="std">
<pre>
// 20.8.1.2.1, constructors
constexpr unique_ptr() noexcept;
explicit unique_ptr(pointer p) noexcept;
unique_ptr(pointer p, see below d1) noexcept;
unique_ptr(pointer p, see below d2) noexcept;
unique_ptr(unique_ptr&& u) noexcept;
constexpr unique_ptr(nullptr_t) noexcept
  : unique_ptr() { }
template &lt;class U, class E&gt;
  unique_ptr(unique_ptr&lt;U, E&gt;&& u) noexcept;
<del>template &lt;class U&gt;
  unique_ptr(auto_ptr&lt;U&gt;&& u) noexcept;</del>
</pre>
</blockquote>

<p>Change 20.8.1.2.1 (unique_ptr.single.ctor) to delete paragraphs 22 through 24.</p>

<blockquote class="std">
<pre>
<del>template &lt;class U&gt;	
unique_ptr(auto_ptr&lt;U&gt;&& u) noexcept;<br>
-22- Effects: Constructs a unique_ptr object, initializing the stored pointer with u.release() and valueinitializing
the stored deleter.
-23- Postconditions: get() yields the value u.get() yielded before the construction. u.get() == nullptr.
get_deleter() returns a reference to the stored deleter.
-24- Remarks: This constructor shall not participate in overload resolution unless U* is implicitly convertible
to T* and D is the same type as default_delete&lt;T&gt;.</del>
</pre>
</blockquote>

<p>Change in 20.8.2.2 (util.smartptr.shared):</p>

<blockquote class="std">
<pre>
// 20.8.2.2.1, constructors:
constexpr shared_ptr() noexcept;
template&lt;class Y&gt; explicit shared_ptr(Y* p);
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);
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);
template&lt;class Y&gt; shared_ptr(const shared_ptr&lt;Y&gt;& r, T* p) noexcept;
shared_ptr(const shared_ptr& r) noexcept;
template&lt;class Y&gt; shared_ptr(const shared_ptr&lt;Y&gt;& r) noexcept;
shared_ptr(shared_ptr&& r) noexcept;
template&lt;class Y&gt; shared_ptr(shared_ptr&lt;Y&gt;&& r) noexcept;
template&lt;class Y&gt; explicit shared_ptr(const weak_ptr&lt;Y&gt;& r);
<del>template&lt;class Y&gt; shared_ptr(auto_ptr&lt;Y&gt;&& r);</del>
template &lt;class Y, class D&gt; shared_ptr(unique_ptr&lt;Y, D&gt;&& r);
constexpr shared_ptr(nullptr_t) : shared_ptr() { }<br>
// 20.8.2.2.2, destructor:
~shared_ptr();<br>
// 20.8.2.2.3, assignment:
shared_ptr& operator=(const shared_ptr& r) noexcept;
template&lt;class Y&gt; shared_ptr& operator=(const shared_ptr&lt;Y&gt;& r) noexcept;<br>
shared_ptr& operator=(shared_ptr&& r) noexcept;
template&lt;class Y&gt; shared_ptr& operator=(shared_ptr&lt;Y&gt;&& r) noexcept;
<del>template&lt;class Y&gt; shared_ptr& operator=(auto_ptr&lt;Y&gt;&& r);</del>
template &lt;class Y, class D&gt; shared_ptr& operator=(unique_ptr&lt;Y, D&gt;&& r);
</pre>
</blockquote>

<p>Change 20.8.2.2.1 (util.smartptr.shared.const) to remove paragraphs 28 through 32:</p>

<blockquote class="std">
<pre>
<del>template&lt;class Y&gt; shared_ptr(auto_ptr&lt;Y&gt;&& r);<br>
-28- Requires: r.release() shall be convertible to T*. Y shall be a complete type. The expression delete
r.release() shall be well formed, shall have well defined behavior, and shall not throw exceptions.
-29- Effects: Constructs a shared_ptr object that stores and owns r.release().
-30- Postconditions: use_count() == 1 && r.get() == 0.
-31- Throws: bad_alloc, or an implementation-defined exception when a resource other than memory
could not be obtained.
-32- Exception safety: If an exception is thrown, the constructor has no effect.</del>
</pre>
</blockquote>

<p>Change 20.8.2.2.3 (util.smartptr.shared.assign):</p>

<blockquote class="std">
<pre>
shared_ptr& operator=(const shared_ptr& r) noexcept;
template&lt;class Y&gt; shared_ptr& operator=(const shared_ptr&lt;Y&gt;& r) noexcept;
<del>template&lt;class Y&gt; shared_ptr& operator=(auto_ptr&lt;Y&gt;&& r);</del>
-1- Effects: Equivalent to shared_ptr(r).swap(*this).
-2- Returns: *this.
</pre>
</blockquote>

<p>Remove D.10 (depr.auto.ptr).</p>

<h2>LWG Issues Impact</h2>

<p>2118. [CD] unique_ptr for array does not support cv qualification conversion of actual argument</p>
<p>Issue 2118 has a current status of Review. The original wording to resolve 2118 involved additional usage of <code>auto_ptr</code>. 
This wording has been superseded by N4089 which does not reference <code>auto_ptr</code>. The proposed
wording changes from this proposal should not impact N4089.</p>

<p>2399. shared_ptr's constructor from unique_ptr should be constrained</p>
<p>Issue 2399 has a current status of Ready. Stephan noted that this issue would affect the <code>shared_ptr</code> constructor from <code>auto_ptr</code>. 
With the proposed changes, the noted issue with the <code>shared_ptr</code> constructor from <code>auto_ptr</code> 
would no longer be valid. The current wording to resolve 2399 should not be impacted.</p>

<h2>Acknowledgements</h2>
Thanks to Howard Hinnant for the inspiration and for reviewing an early draft.
</body>
</html>
