<!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><th> </th><td>P0357R3</td>
  </tr>
  <tr>
    <th>Date:&nbsp;&nbsp;</th><th> </th><td>2018-11-07</td>
  </tr>
  <tr>
    <th>Project:&nbsp;&nbsp;</th><th> </th><td>Programming Language C++, Library Working Group</td>
  </tr>
  <tr>
    <th>Reply-to:&nbsp;&nbsp;</th><th> </th><td><address>Tomasz Kamiński &lt;tomaszkam at gmail dot com&gt;</address></td>
  </tr>
  <tr>
    <th>                     </th><th> </th><td><address>Stephan T. Lavavej &lt;stl at microsoft dot com&gt;</address></td>
  </tr>
  <tr>
    <th>                     </th><th> </th><td><address>Alisdair Meredith &lt;ameredith1 at bloomberg dot net&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 a change in <code>reference_wrapper</code>'s specification to
   support incomplete types.</p>

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

<h2><a name="history">2. History</a></h2>

<h3><a name="history.r1">2.1. Revision 1</a></h3>

<ul>
  <li>Minor corrections and clarifications to paper text. Clarified relation to
      <a href="https://wg21.link/p0091r3">P0091: Template argument deduction for class templates</a></li>
  <li>Updated wording to refer to <a href="https://wg21.link/n4606">N4606</a> (C++ Working Draft, 2016-07-12)
      and included content of removed subclause.</li>
  <li>Included proposed feature testing recommendation macro.</li>
  <li>Corrected included implementation for the <code>operator()</code> of <code>reference_wrapper</code>, so it is now const qualified.</li>
  <li>Extended implementability section to discuss details of instantiation of <code>reference_wrapper</code> and <code>operator()</code> member.</li>
</ul>

<h3><a name="history.r2">2.2. Revision 2</a></h3>

<ul>
  <li>Updated wording to <a href="https://wg21.link/n4750">N4750</a> (C++ Working Draft, 2018-05-07).</li>
  <li>Dropped uncessary removal wording (accepted as part of <a href="https://wg21.link/p0619r4">P0619R4</a>).</li>
  <li>Updated discussion section of paper to match current state of C++20.</li>
</ul>

<h3><a name="history.r3">2.3. Revision 3</a></h3>

<ul>
  <li>Updated wording to <a href="http://wg21.link/n4778">N4778</a> (C++ Working Draft, 2018-10-08).</li>
  <li>Replaced "Remarks" element with "Mandates", per <a href="http://wg21.link/p0788r3">P0788R3: Standard Library Specification in a Concepts and Contracts World</a>.</li>
  <li>Changed links to use <a href="https://wg21.link">https://wg21.link</a>.</li>
</ul>

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

<p><code>std::reference_wrapper</code> is a utility class created to
   allow references to be used in interfaces that were designed to pass
   objects by value. However the 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 a 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 the case when the 
   definition of the class is not available to the programmer.</p>

<p>Moreover <code>std::reference_wrapper</code> specializations are
   recognized by standard factory functions, like: <code>std::make_pair</code>,
   <code>std::make_tuple</code> or <code>std::bind</code> which allow
   the programmer to create pairs of references by use of:</p>
<pre>auto p = std::make_pair(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 the case of the following
   definition:</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
   reading a dangling reference. Despite all of the above advantages, programmers
   are still forced to use <code>pair&lt;T&amp;, U&amp;&gt;</code>, when at least
   one of the types <code>T</code> or <code>U</code> is incomplete.</p>

<p>Furthermore this problem is not addressed by inclusion of the
   <a href="https://wg21.link/p0091r3">P0091: Template argument deduction for class templates</a>,
   as implicit deduction guides synthesized from <code>pair</code> and <code>tuple</code>
   constructors do not deduce reference types.</p>

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

<p>Supporting incomplete types in <code>reference_wrapper</code> was impossible until
   recent removal of <code>result_type</code> and related typedefs introduced by
   <a href="https://wg21.link/p0619r4">P0619: Reviewing Deprecated Facilities of C++17 for C++20</a>,
   as to provide them, implementations were required to check the template parameter for their presence.</p>

<h3><a name="design.removal">4.1. Forced removal of nested typedefs</a></h3>

<p>The feature proposed in this paper conflicts with support for the old
   function binding protocol and vendors will no longer be allowed to provide required
   typedefs in their <code>std::reference_wrapper</code> implementations.</p>

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

<p>In C++14, another protocol based on the presence of the <code>is_transparent</code>
   nested type was introduced, to indicate that a given functor enables heterogeneous lookup
   for associative container. As in the 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 the possibility to 
   provide both of them, via an alternative design that relies on a metafunction instead of
   a nested type, as proposed in <a href="https://wg21.link/p0046r1">
   P0046R1: Change is_transparent to metafunction (Revision 1)</a>.</p>

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

<p>This proposal depends on the removal of the <code>result_type</code> and related typedefs for C++20.</p>

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


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

<p>The proposed wording changes refer to <a href="https://wg21.link/n4778">N4778</a> (C++ Working Draft, 2018-10-08).</p>

<p>At the end of the section 23.14.5 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 23.14.5.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><ins>Mandates:</ins></dt>
    <dd><p><ins><code>T</code> is a complete type.</ins></p></dd>

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

  </dl>
</blockquote>

<p>At the beginning of the paragraph 23.14.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>

<h2><a name="feature-testing">7. Feature-testing recommendation</a></h2>

<p>For the purposes of SG10, we recommend the macro name <code>__cpp_lib_reference_wrapper</code>
with value <code>20<em>YYMM</em></code> representing publication date, to be defined in the
<code>&lt;functional&gt;</code> header. The intent is to allow reuse of the same macro to
indicate presence of the original feature from C++11 standard.</p>

<p>Usage example:</p>
<pre>template&lt;typename T, typename U&gt;
auto my_tie(T&amp; t, U &amp; u)
{
#if __cpp_lib_reference_wrapper &gt;= 20<em>YYMM</em>
  return std::make_pair(std::ref(t), std::ref(u));
#else
  return std::pair&lt;T&amp;, U&amp;&gt;(t, u);
#endif
}</pre>

<h2><a name="implementability">8. 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) const
    -&gt; std::result_of_t&lt;T&amp;(Args...)&gt;
  { return std::invoke(*ptr, std::forward&lt;Args&gt;(args)...); }
};</pre>

<p>Careful reader may notice, that the  <code>operator()</code> requires template parameter <code>T</code> to be a complete type,
   and this requirement is not only limited to definition of the function, but also its declaration, that uses 
   <code>std::result_of_t&lt;T&amp;(Args...)&gt;</code> to specify return type. 
   However, call operator is an template function member of the class and its declaration will not be instantiated during the
   instantiation of enclosing <code>reference_wrapper</code> specialization, as the <code>Args</code> template parameter pack 
   are not know at this point. As a consequence the user is allowed to use an object of <code>reference_wrapper&lt;T&gt;</code>
   with <code>T</code> being an incomplete type, unless it is actually called.</p>

<h2><a name="acknowledgements">9. 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">10. References</a></h2>

<ol>
  <li>Tomasz Kamiński, Stephan T. Lavavej, Alisdair Meredith,
      "Reviewing Deprecated Facilities of C++17 for C++20",
      (P0619R4,  <a href="https://wg21.link/p0619r4">https://wg21.link/p0619r4</a>)</li>

  <li>Tomasz Kamiński, 
      "Change is_transparent to metafunction (Revision 1)",
      (P0046R1, <a href="https://wg21.link/p0046r1">https://wg21.link/p0046r1</a>)</li>

  <li>Mike Spertus, Faisal Vali, Richard Smith,
      "Template argument deduction for class templates (Rev. 6)",
      (P0091R3, <a href="https://wg21.link/p0091r3">https://wg21.link/p0091r3</a>)</li>

  <li>Richard Smith, 
      "Working Draft, Standard for Programming Language C++" 
      (N4778, <a href="https://wg21.link/n4778">https://wg21.link/n4778</a>)</li>

  <li>Walter E. Brown,
      "Standard Library Specification in a Concepts and Contracts World"
      (P0788R3, <a href="http://wg21.link/p0788r3">http://wg21.link/p0788r3</a>)</li>

</ol>


</body></html>
