<!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>P0357R1</td>
  </tr>
  <tr>
    <th>Date:&nbsp;&nbsp;</th><th> </th><td>2016-09-29</td>
  </tr>
  <tr>
    <th>Project:&nbsp;&nbsp;</th><th> </th><td>Programming Language C++, Library Evolution 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.com&gt;</address></td>
  </tr>
  <tr>
    <th>                     </th><th> </th><td><address>Alisdair Meredith &lt;ameredith1 at bloomberg.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>

<p>In addition to the 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 the D7. Old adaptable function bindings
   [depr.func.adaptor.binding] section of the standard. As a consequence this paper
   may be viewed as a 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>.

<!--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="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0091r3.html">P0091: Template argument deduction for class templates</a></li>
  <li>Updated wording to refer to <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4606.pdf">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>


<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 types the <code>T</code> or <code>U</code> is incomplete.</p>

<p>Furthermore this problem is not addressed by inclusion of the
   <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0091r3.html">P0091: Template argument deduction for class templates</a>,
   as implicit deduction guides synthesized from <code>pair</code> and <code>tuple</code>
   constructors will not deduce reference types. And if special treatment of
   <code>std::reference_wrapper&lt;T&gt;</code> will be reintroduced, the same limitations
   will apply (<code>T</code> needs to be a complete type).</p>

<h2><a name="design">4. 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 a consequence support for these
   (now deprecated) features needs to be removed from the standard.</p>

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

<p>Despite the fact that support for incomplete types requires only removal of support
   for <i>weak result type</i> and argument typedefs for <code>reference_wrapper</code>,
   this paper follows 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
   the next standard after C++17, it also follows the committee guideline to introduce a
   period of deprecation before removal.</p> 

<p>In addition, the feature proposed with the 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="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">5. Impact On The Standard</a></h2>

<p>This proposal depends on the deprecation of the <code>result_type</code> and related
   typedefs in C++17, so they can be removed in an upcoming standard after a period of deprecation.</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="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4606.pdf">N4606</a> (C++ Working Draft, 2016-07-12).</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>,
    <ins><code>binary_negate</code>,</ins>
    <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>,
    <code>mem_fun1_ref_t</code>,
    <code>mem_fun1_t</code>,
    <del><code>mem_fun_ref_t</code>,</del>
    <ins><code>mem_fun</code>,</ins>
    <code>mem_fun_ref</code>,
    <ins><code>mem_fun_ref_t</code>,</ins>
    <code>mem_fun_t</code>,
    <del><code>mem_fun</code>,</del>
    <ins><code>not1</code>,</ins>
    <ins><code>not2</code>,</ins>
    <code>pointer_to_binary_function</code>,
    <code>pointer_to_unary_function</code>,
    <code>ptr_fun</code>,
    <code>random_shuffle</code>,
    <del>and </del><code>unary_function</code><ins>,</ins>
    <ins>and <code>unary_negate</code></ins>.
    </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.14.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.14.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 beginning of the paragraph 20.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>

<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 subclause D8. Old adaptable function bindings [depr.func.adaptor.binding] entirely:</p>

<blockquote class="stddel">
<h3><a name="6.16">D.8 Old Adaptable Function Bindings  <span style="float:right">[depr.func.adaptor.binding]</span></a></h3>

<h4><a name="6.16.1">D.8.1 Weak Result Types <span style="float:right">[depr.weak.result_type]</a></h4>
<ol>
  <li>If a call wrapper (20.9.1) has a <i>weak result type</i>, the type of its member
      type <tt>result_type</tt> is based on the type <tt>T</tt> of the wrapper's target object
      (20.9.1):</li>
  <ol>
    <li>if <tt>T</tt> is a pointer to function type, <tt>result_type</tt> shall be a
        synonym for the return type of <tt>T</tt>;</li>
    <li>if <tt>T</tt> is a pointer to member function, <tt>result_type</tt> shall be a
        synonym for the return type of <tt>T</tt>;</li>
    <li>if <tt>T</tt> is a class type and the qualified-id <tt>T::result_type</tt> is
        valid and denotes a type (14.8.2), then <tt>result_type</tt> shall be a synonym for
        <tt>T::result_type</tt>;</li>
    <li>otherwise <tt>result_type</tt> shall not be defined.</li>
  </ol>
</ol>


<h4><a name="6.16.2">D.8.2 Typedefs to Support Function Binders <span style="float:right">[depr.func.adaptor.typedefs]</span></a></h4>

<ol>
<li>
To enable old function adaptors to manipulate function objects that take one or
two arguments, many of the function objects in this standard correspondingly
provide typedefs <tt>argument_type</tt> and <tt>result_type</tt> for function
objects that take one argument and <tt>first_argument_type</tt>,
<tt>second_argument_type</tt>, and <tt>result_type</tt> for function objects
that take two arguments.
</li>

<li>
The following member names are defined in addition to names specified in Clause 20:


<pre>
namespace std {
  template&lt;class T&gt; struct owner_less&lt;shared_ptr&lt;T&gt; &gt; {
    typedef bool result_type;
    typedef shared_ptr&lt;T&gt; first_argument_type;
    typedef shared_ptr&lt;T&gt; second_argument_type;
  };

  template&lt;class T&gt; struct owner_less&lt;weak_ptr&lt;T&gt; &gt; {
    typedef bool result_type;
    typedef weak_ptr&lt;T&gt; first_argument_type;
    typedef weak_ptr&lt;T&gt; second_argument_type;
  };

  template &lt;class T&gt; class reference_wrapper {
  public :
    typedef <i>see below</i> result_type;              <i>// not always defined</i>
    typedef <i>see below</i> argument_type;            <i>// not always defined</i>
    typedef <i>see below</i> first_argument_type;      <i>// not always defined</i>
    typedef <i>see below</i> second_argument_type;     <i>// not always defined</i>
  };

  template &lt;class T = void&gt; struct plus {
    typedef T first_argument_type;
    typedef T second_argument_type;
    typedef T result_type;
  };

  template &lt;class T = void&gt; struct minus {
    typedef T first_argument_type;
    typedef T second_argument_type;
    typedef T result_type;
  };

  template &lt;class T = void&gt; struct multiplies {
    typedef T first_argument_type;
    typedef T second_argument_type;
    typedef T result_type;
  };

  template &lt;class T = void&gt; struct divides {
    typedef T first_argument_type;
    typedef T second_argument_type;
    typedef T result_type;
  };

  template &lt;class T = void&gt; struct modulus {
    typedef T first_argument_type;
    typedef T second_argument_type;
    typedef T result_type;
  };

  template &lt;class T = void&gt; struct negate {
    typedef T argument_type;
    typedef T result_type;
  };

  template &lt;class T = void&gt; struct equal_to {
    typedef T first_argument_type;
    typedef T second_argument_type;
    typedef bool result_type;
  };

  template &lt;class T = void&gt; struct not_equal_to {
    typedef T first_argument_type;
    typedef T second_argument_type;
    typedef bool result_type;
  };

  template &lt;class T = void&gt; struct greater {
    typedef T first_argument_type;
    typedef T second_argument_type;
    typedef bool result_type;
  };

  template &lt;class T = void&gt; struct less {
    typedef T first_argument_type;
    typedef T second_argument_type;
    typedef bool result_type;
  };

  template &lt;class T = void&gt; struct greater_equal {
    typedef T first_argument_type;
    typedef T second_argument_type;
    typedef bool result_type;
  };

  template &lt;class T = void&gt; struct less_equal {
    typedef T first_argument_type;
    typedef T second_argument_type;
    typedef bool result_type;
  };

  template &lt;class T = void&gt; struct logical_and {
    typedef T first_argument_type;
    typedef T second_argument_type;
    typedef bool result_type;
  };

  template &lt;class T = void&gt; struct logical_or {
    typedef T first_argument_type;
    typedef T second_argument_type;
    typedef bool result_type;
  };

  template &lt;class T = void&gt; struct logical_not {
    typedef T argument_type;
    typedef bool result_type;
  };

  template &lt;class T = void&gt; struct bit_and {
    typedef T first_argument_type;
    typedef T second_argument_type;
    typedef T result_type;
  };

  template &lt;class T = void&gt; struct bit_or {
    typedef T first_argument_type;
    typedef T second_argument_type;
    typedef T result_type;
  };

  template &lt;class T = void&gt; struct bit_xor {
    typedef T first_argument_type;
    typedef T second_argument_type;
    typedef T result_type;
  };

  template &lt;class T = void&gt; struct bit_not {
    typedef T argument_type;
    typedef T result_type;
  };

  template&lt;class R, class... ArgTypes&gt;
  class function&lt;R(ArgTypes...)&gt; {
  public:
    typedef T1 argument_type;          <i>// only if sizeof...(ArgTypes) == 1 and</i>
                                       <i>// the type in ArgTypes is T1</i>
    typedef T1 first_argument_type;    <i>// only if sizeof...(ArgTypes) == 2 and</i>
                                       <i>// ArgTypes contains T1 and T2</i>
    typedef T2 second_argument_type;   <i>// only if sizeof...(ArgTypes) == 2 and</i>
                                       <i>// ArgTypes contains T1 and T2</i>
  };
}
</pre>
</li>

<li><tt>reference_wrapper&lt;T&gt;</tt> has a weak result type (D.x.1). If
<tt>T</tt> is a function type, <tt>result_type</tt> shall be a synonym for the
return type of <tt>T</tt>.
</li>
<li>
The template specialization <tt>reference_wrapper&lt;T&gt;</tt> shall define
a nested type named <tt>argument_type</tt> as a synonym for <tt>T1</tt> only if
the type <tt>T</tt> is any of the following:

<ol>
<li>
- a function type or a pointer to function type taking one argument of
type <tt>T1</tt>
</li>
<li>
- a pointer to member function <tt>R T0::f <i>cv</i></tt> (where
<tt><i>cv</i></tt> represents the member function's <i>cv</i>-qualifiers); the
type <tt>T1</tt> is <tt><i>cv</i> T0*</tt>
</li>
<li>
- a class type where the qualified-id <tt>T::argument_type</tt> is valid
and denotes a type (14.8.2); the type <tt>T1</tt> is <tt>T::argument_type</tt>.
</li>
</ol></li>
<li>
The template instantiation <tt>reference_wrapper&lt;T&gt;</tt> shall define
two nested types named <tt>first_argument_type</tt> and
<tt>second_argument_type</tt> as synonyms for <tt>T1</tt> and <tt>T2</tt>,
respectively, only if the type <tt>T</tt> is any of the following:

<ol>
<li>
- a function type or a pointer to function type taking two arguments of
types <tt>T1</tt> and <tt>T2</tt>
</li>
<li>
- a pointer to member function <tt>R T0::f(T2) <i>cv</i></tt> (where
<tt><i>cv</i></tt> represents the member function's <i>cv</i>-qualifiers); the
type <tt>T1</tt> is <tt><i>cv</i> T0*</tt>
</li>
<li>
- a class type where the qualified-ids <tt>T::first_argument_type</tt>
and <tt>T::second_argument_type</tt> are both valid and both denote types
(14.8.2); the type <tt>T1</tt> is <tt>T::first_argument_type</tt> and the type
<tt>T2</tt> is <tt>T::second_argument_type</tt>.
</li>
</ol></li>
<li>
For all object types <tt>Key</tt> for which there exists a specialization
<tt>hash&lt;Key&gt;</tt>, and for all enumeration types (7.2) <tt>Key</tt>, the
instantiation <tt>hash&lt;Key&gt;</tt> shall provide two nested types,
<tt>result_type</tt> and <tt>argument_type</tt>, which shall be synonyms for
<tt>size_t</tt> and <tt>Key</tt>, respectively.
</li>
<li>
The forwarding call wrapper <tt>g</tt> returned by a call to
<tt>bind(f, bound_args...)</tt> (20.9.10.3) shall have a weak result type (D.x.1).
</li>
<li>
The forwarding call wrapper <tt>g</tt> returned by a call to
<tt>bind&lt;R&gt;(f, bound_args...)</tt> (20.9.10.3) shall have a nested type
<tt>result_type</tt> defined as a synonym for <tt>R</tt>.
</li>
<li>
The simple call wrapper returned from a call to
<tt>mem_fn(pm)</tt> shall have a nested type <tt>result_type</tt> that is a
synonym for the return type of <tt>pm</tt> when <tt>pm</tt> is a pointer to
member function.
</li>
<li>
The simple call wrapper returned from a call to
<tt>mem_fn(pm)</tt> shall define two nested types named
<tt>argument_type</tt> and <tt>result_type</tt> as synonyms for
<tt><i>cv</i> T*</tt> and <tt>Ret</tt>, respectively, when <tt>pm</tt> is a
pointer to member function with <i>cv</i>-qualifier <i>cv</i> and taking no
arguments, where <tt>Ret</tt> is <tt>pm</tt>'s return type.
</li>
<li>
The simple call wrapper returned from a call to
<tt>mem_fn(pm)</tt> shall define three nested types named
<tt>first_argument_type</tt>, <tt>second_argument_type</tt>, and
<tt>result_type</tt> as synonyms for <tt>cv T*</tt>, <tt>T1</tt>, and
<tt>Ret</tt>, respectively, when <tt>pm</tt> is a pointer to member function
with <i>cv</i>-qualifier <i>cv</i> and taking one argument of type <tt>T1</tt>,
where <tt>Ret</tt> is <tt>pm</tt>'s return type.
</li>
<li>
The following member names are defined in addition to names specified in Clause 23:

<pre>
namespace std {
  template &lt;class Key, class T, class Compare = less&lt;Key&gt;,
            class Allocator = allocator&lt;pair&lt;const Key, T&gt;&gt;&gt;
  class map {
  public:
     class value_compare {
     public:
       typedef bool result_type;
       typedef value_type first_argument_type;
       typedef value_type second_argument_type;
       }
    };
  };

  template &lt;class Key, class T, class Compare = less&lt;Key&gt;,
            class Allocator = allocator&lt;pair&lt;const Key, T&gt;&gt;&gt;
  class multimap {
  public:
     class value_compare {
     public:
       typedef bool result_type;
       typedef value_type first_argument_type;
       typedef value_type second_argument_type;
    };
  };
}
</pre>
</li>
</ol>

<h4><a name="6.16.3">D.8.3 Negators <span style="float:right">[depr.negators]</span></a></h4>
<ol>
<li>
The header <tt>&lt;functional&gt;</tt> has the following additional declarations:
<pre>
namespace std {
  template &lt;class Predicate&gt; class unary_negate;
  template &lt;class Predicate&gt;
    constexpr unary_negate&lt;Predicate&gt; not1(const Predicate&amp;);
  template &lt;class Predicate&gt; class binary_negate;
  template &lt;class Predicate&gt;
    constexpr binary_negate&lt;Predicate&gt; not2(const Predicate&amp;);
}
</pre>
</li>
<li>
Negators <tt>not1</tt> and <tt>not2</tt> take a unary and a binary predicate,
respectively, and return their complements (5.3.1).
</li>

<p><pre>
   template &lt;class Predicate&gt;
     class unary_negate {
   public:
     constexpr explicit unary_negate(const Predicate&amp; pred);
     constexpr bool operator()(const typename Predicate::argument_type&amp; x) const;
     typedef typename Predicate::argument_type argument_type;
     typedef bool result_type;
   };
</pre></p>

<li>
<tt>operator()</tt> returns <tt>!pred(x)</tt>.
</li>

<p><pre>
 template &lt;class Predicate&gt;
     constexpr unary_negate&lt;Predicate&gt; not1(const Predicate&amp; pred);
</pre></p>

<li>
<i>Returns:</i> <tt>unary_negate&lt;Predicate&gt;(pred)</tt>.
</li>

<p><pre>
  template &lt;class Predicate&gt;
  class binary_negate {
  public:
    constexpr explicit binary_negate(const Predicate&amp; pred);
    constexpr bool operator()(const typename Predicate::first_argument_type&amp; x,
                              const typename Predicate::second_argument_type&amp; y) const;
    typedef typename Predicate::first_argument_type first_argument_type;
    typedef typename Predicate::second_argument_type second_argument_type;
    typedef bool result_type;
  };
</pre></p>

<li>
<tt>operator()</tt> returns <tt>!pred(x,y)</tt>.
</li>

<p><pre>
template &lt;class Predicate&gt;
  constexpr binary_negate&lt;Predicate&gt; not2(const Predicate&amp; pred);
</pre></p>

<li>
<i>Returns:</i> <tt>binary_negate&lt;Predicate&gt;(pred)</tt>.
</li>
</ol>

</ol>

</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>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>Mike Spertus, Faisal Vali, Richard Smith,
      "Template argument deduction for class templates (Rev. 6)",
      (P0091R3, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0091r3.html">
               http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0091r3.html</a>)</li>

           
  <li>Richard Smith, 
      "Working Draft, Standard for Programming Language C++" 
      (N4606, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n4606.pdf">
              http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n4606.pdf</a>)</li>
</ol>


</body></html>
