<!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">
pre {margin-left:20pt; }
pre > i {
  font-family: "OCR A Extended", "Consolas", "Lucida Console", monospace;
  font-style:italic;
}
code > i {
  font-family: "OCR A Extended", "Consolas", "Lucida Console", monospace;
  font-style:italic;
}
pre > em {
  font-family: "OCR A Extended", "Consolas", "Lucida Console", monospace;
  font-style:italic;
}
code > em {
  font-family: "OCR A Extended", "Consolas", "Lucida Console", monospace;
  font-style:italic;
}
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.5empadding-right: 0.5em; ; }

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

table.header { border: 0px; border-spacing: 0;
  margin-left: 0px; font-style: normal; }

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

<title>'reference_wrapper' for incomplete types</title>
</head>

<body>

<table class="header"><tbody>
  <tr>
    <th>Document number:&nbsp;&nbsp;<th>P0357R0<td></td>
  </tr>
  <tr>
    <th>Date:&nbsp;&nbsp;<th> <td>2016-05-24</td>
  </tr>
  <tr>
    <th>Project:&nbsp;&nbsp;<th> <td>Programming Language C++, Library Evolution Working Group</td>
  </tr>
  <tr>
    <th>Reply-to:&nbsp;&nbsp;<th> <td><address>Tomasz Kamiński &lt;tomaszkam at gmail dot com&gt;</address></td>
  </tr>
  <tr>
    <th><th>                      <td><address>Stephan T. Lavavej &lt;stl at microsoft.com&gt;</address></td>
  </tr>
</tbody></table>

<h1><a name="title"><code>reference_wrapper</code> for incomplete types</a></h1>

<h2><a name="intro">1. Introduction</a></h2>

<p>This paper proposes change in <code>reference_wrapper</code> specification to
   support incomplete types.</p>

<p>In addition to necessary removal of <code>result_type</code> and related typedefs
   for <code>reference_wrapper</code>, the paper proposes to remove all deprecated
   functional components placed in D7. Old adaptable function bindings
   [depr.func.adaptor.binding] section of the standard. As consequence this paper
   may be viewed as successor of <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0005r4.html">
   P0005R4: Adopt <code>not_fn</code> from Library Fundamentals 2 for C++17</a> paper.

<!--h2><a name="toc">Table of contents</a></h2-->

<h2><a name="motivation">2. Motivation and Scope</a></h2>

<p><code>std::reference_wrapper</code> is an utility class created to allow to
   use reference in the interface that was designed to pass objects by value.
   However design of the standard component has a major drawback, when
   compared to the alternative solutions based on the use of the raw 
   pointers of boost version of this component: the referenced type is
   required to be complete. As consequence, depending on the context
   use of <code>reference_wrapper</code> may increase compilation time
   by adding a new definition, or even be impossible in case when definition
   of the class is not available to the programmer.</p>

<p>Moreover <code>std::reference_wrapper</code> specializations are
   recognized by standard factory function, like: <code>std::make_pair</code>,
   <code>std::make_tuple</code> or <code>std::bind</code> and allows
   the programmer to create tuple of references by use of:</p>
<pre>std::make_tuple(std::ref(t), std::ref(u))</pre>
<p>Use of this feature, not only avoids cumbersome specification of the
   type, but also eliminates the possibility of encountering dangling reference
   problems that it may introduce. For example in case of following declaration:</p>
<pre>std::pair&lt;std::string const&amp;, int&gt; p("test", 10);</pre>
<p>every use of <code>p.first</code> leads to undefined behaviour caused by
   read of dangling reference. Despite of all of above advantages, programmes
   are still forced to use <code>pair&lt;T&amp;, U&amp;&gt;</code> solution, when
   at least one of types <code>T</code> or <code>U</code> is incomplete.</p>

<h2><a name="design">3. Design Decisions</a></h2>

<p>Supporting incomplete types in <code>reference_wrapper</code> is currently impossible
   because the implementation is required to check the template parameter for presence
   of <code>result_type</code> and related nested types. As consequence support for this
   (now deprecated) features needs to be removed from standard.</p>

<h3><a name="design.removal">3.1. Removal of deprecated functional components</a></h3>

<p>Despite the fact that support for incomplete types require only removal support for
   <i>weak result type</i> and argument typedefs for <code>reference_wrapper</code>,
   this paper follow the original direction of <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0005r4.html">P005R4: Adopt <code>not_fn</code> from Library Fundamentals 2 for C++17</a>
   and proposes removal of all deprecated function bindings. As this paper is targeted for next standard
   after C++17, it also follows committee guideline to introduce period of deprecation before removal.</p> 

<p>In addition feature proposed with the paper conflicts with support for the old function
   binding protocol and vendors will not longer be allowed to provide it in their
   <code>std::reference_wrapper</code> implementations.</p>

<h3><a name="design.is_transparent">3.2. Support for <code>is_transparent</code></a></h3>

<p>In the C++14, another protocol based on the presence of the <code>is_transparent</code>
   nested type was introduced, to indicate that given functor enables heterogeneous lookup
   for associative container. As in case of <code>result_type</code> implementation of this
   protocol in exact form for <code>reference_wrapper&lt;T&gt;</code> would reintroduce 
   requirement of completeness of <code>T</code> template parameter.</p>

<p>Despite the fact that support for incomplete types and heterogeneous container lookup
   in <code>reference_wrapper</code> may look incompatible, there is possibility to provide
   both of them, via alternative design that rely on use metafunction instead of nested type,
   as proposed in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0046r1.html">
   P0046R1: Change is_transparent to metafunction (Revision 1)</a>.</p>

<h2><a name="standard">4. Impact On The Standard</a></h2>

<p>This proposal depends on the deprecation of the <code>result_type</code> and related typedefs in the C++17,
   so they can be removed in upcoming standard after period of deprecation.</p>

<p>Nothing depends on this proposal.</p>


<h2><a name="wording">5. Proposed Wording</a></h2>

<p>The proposed wording changes refer to <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4582.pdf">N4582</a> (C++ Working Draft, 2016-03-19).</p>

<p>Apply following changes to paragraph 17.6.4.3.1 Zombie names [zombie.names]:</p>
<blockquote class="std"> 
  <dl class="attribute">

    <dd><p>In namespace <code>std</code>, the following names are reserved for previous standardization:
    <code>auto_ptr</code><code></code>,
    <code>binary_function</code><code></code>,
    <code>bind1st</code>,
    <code>bind2nd</code>,
    <code>binder1st</code>,
    <code>binder2nd</code>,
    <code>const_mem_fun1_ref_t</code>,
    <code>const_mem_fun1_t</code>,
    <code>const_mem_fun_ref_t</code>,
    <code>const_mem_fun_t</code>,
    <ins>
    <code>not1</code>, 
    <code>not2</code>, 
    <code>unary_negate</code>, 
    <code>binary_negate</code>,
    </ins>
    <code>mem_fun1_ref_t</code>,
    <code>mem_fun1_t</code>,
    <code>mem_fun_ref_t</code>,
    <code>mem_fun_ref</code>,
    <code>mem_fun_t</code>,
    <code>mem_fun</code>,
    <code>pointer_to_binary_function</code>,
    <code>pointer_to_unary_function</code>,
    <code>ptr_fun</code>,
    <code>random_shuffle</code>,
    and <code>unary_function</code>.
    </p></dd>

    <dd><p><ins>It is unspecified whether function objects in the C++ standard library additionally
        provide the following typedefs: <code>result_type</code>, <code>argument_type</code>,
        <code>first_argument_type</code>, and <code>second_argument_type</code>.</ins></p></dd>

  </dl>
</blockquote>

<p>At the end of the section 20.12.4 Class template <code>reference_wrapper</code> [refwrap]:</p>
<blockquote class="std"> 
  <dl class="attribute">
    <dd><p><ins>The template parameter <code>T</code> of <code>reference_wrapper</code>
      may be an incomplete type.</ins></p></dd>
  </dl>
</blockquote>


<p>Apply following changes to paragraph 20.12.4.4 <code>reference_wrapper</code> invocation [refwrap.invoke]:</p>
<blockquote class="std"> 
<pre>  template &lt;class... ArgTypes&gt;
    result_of_t&lt;T&amp;(ArgTypes&amp;&amp;... )&gt;
      operator()(ArgTypes&amp;&amp;... args) const;
</pre>
  <dl class="attribute">

    <dt>Returns:</dt> 
    <dd><p><code><em>INVOKE</em>(get(), std::forward&lt;ArgTypes&gt;(args)...)</code>. ([func.require] 20.12.2).</p></dd>

    <dt><ins>Remarks:</ins></dt>
    <dd><p><ins>If <code>T</code> is an incomplete type, the program is ill-formed.</ins></p></dd>

  </dl>
</blockquote>

<p>At the begining of the paragraph 20.12.4.5 <code>reference_wrapper</code> helper functions [refwrap.helpers]:</p>
<blockquote class="std"> 
  <dl class="attribute">

    <dd><p><ins>The template parameter <code>T</code> of the following <code>ref</code> and <code>cref</code>
      function templates may be an incomplete type.</ins></p></dd>

  </dl>
</blockquote>

<p>Under Annex C Compatibility [diff] add new subclause after C.4 C++ and ISO C++ 2014 [diff.cpp14]:</p>
<blockquote class="stdins"> 

<h3>C.x C++ and ISO C++ 2017 <span style="float:right">[diff.cpp17]</span></h3>

<dl class="attribute">
  <dd><p>This subclause lists the differences between C++ and ISO C++ 2017 (<em>TBD</em>), by the chapters of this document.</p></dd>
</dl>

<h4>C.x.1 Clause 20: general utilities library <span style="float:right">[diff.cpp17.utilities]</span></h4>

  <dl class="attribute">
    <dd><p><b>Change:</b> The typedefs <code>result_type</code>, <code>argument_type</code>, <code>first_argument_type</code>,
        and <code>second_argument_type</code> might not be defined by some function objects.</p></dd>
    <dd><p><b>Rationale:</b> Superseded by new features, including <code>decltype</code> and forwarding references.</p></dd>
    <dd><p><b>Effect on original feature:</b> Valid C++ 2017 code that uses these typedefs may fail to compile in this International Standard.</p></dd>
  </dl>

  <p><br></p>

  <dl class="attribute">
    <dd><p><b>Change:</b> The class templates <code>unary_negate</code> and <code>binary_negate</code> and the function templates
        <code>not1</code> and <code>not2</code> might not be defined.</p></dd>
    <dd><p><b>Rationale:</b> Superseded by new features, including generic lambdas and the function template <code>not_fn</code>.</p></dd>
    <dd><p><b>Effect on original feature:</b> Valid C++ 2017 code that uses these class templates and function templates may fail to compile 
        in this International Standard.</p></dd>
  </dl>
</blockquote>

<p>Remove clause D7. Old adaptable function bindings [depr.func.adaptor.binding] entirely.</p>

<h2><a name='implementability'>6. Implementability</a></h2>

<p>Without requirement to conditionally support <code>result_type</code> and related typedefs, straightforward implementation
   provides support for incomplete types.</p>
<pre>template&lt;typename T&gt;
class reference_wrapper
{
  T* ptr;
    
public:
  using type = T;  
     
  reference_wrapper(T&amp; val) noexcept
     : ptr(std::addressof(val))
  {}

  reference_wrapper(T&amp;&amp;) = delete;
  
  T&amp; get() const noexcept { return *ptr; }
  operator T&amp;() const noexcept{ return *ptr; }

  template&lt;typename... Args&gt;
  auto operator()(Args&amp;&amp;... args)
    -&gt; std::result_of_t&lt;T&amp;(Args...)&gt;
  { return std::invoke(*ptr, std::forward&lt;Args&gt;(args)...); }
};</pre>

<h2><a name="acknowledgements">7. Acknowledgements</a></h2>

<p>Special thanks and recognition goes to Sabre (<a href="http://www.sabre.com/">http://www.sabre.com</a>) for supporting the production of this proposal,
   and for sponsoring Tomasz Kamiński's trip to the Oulu for WG21 meeting.</p>

<h2><a name="literature">8. References</a></h2>

<ol>
  <li>Alisdair Meredith, Stephan T. Lavavej, Tomasz Kamiński, 
      "Adopt <code>not_fn</code> from Library Fundamentals 2 for C++17",
      (P0005R4, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0005r4.html">
                http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0005r4.html</a>)</li>

  <li>Tomasz Kamiński, 
      "Change is_transparent to metafunction (Revision 1)",
      (P0046R1, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0046r1.html">
               http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0046r1.html</a>)</li>
           
  <li>Richard Smith, 
      "Working Draft, Standard for Programming Language C++" 
      (N4582, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n4582.pdf">
              http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n4582.pdf</a>)</li>
</ol>

</body></html>
