<html>

<head>
<title>Adopt 'not_fn' from Library Fundamentals 2 for C++17</title>
<style type="text/css">
  p {text-align:justify}
  li {text-align:justify}
  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}
</style>
</head>

<body>
<table>
<tr>
  <td align="left">Doc. no.</td>
  <td align="left">P0005R2</td>
</tr>
<tr>
  <td align="left">Date:</td>
  <td align="left">2015-10-19</td>
</tr>
<tr>
  <td align="left">Project:</td>
  <td align="left">Programming Language C++</td>
</tr>
<tr>
  <td align="left">Reply to:</td>
  <td align="left">Alisdair Meredith &lt;<a href="mailto:ameredith1@bloomberg.net">ameredith1@bloomberg.net</a>&gt;</td>
</tr>
<tr>
  <td/>
  <td align="left">Stephan T. Lavavej &lt;<a href="mailto:stl@microsoft.com">stl@microsoft.com</a>&gt;</td>
</tr>
<tr>
  <td/>
   <td align="left">Tomasz Kamiński &lt;tomaszkam at gmail dot com&gt;</td>
</tr>
</table>

<h1>Adopt <tt>not_fn</tt> from Library Fundamentals 2 for C++17</tt></h1>

<h2>Table of Contents</h2>
<ul>
<li><a href="#0.0">Revision History</a></li>
  <ul>
  <li><a href="#0.1">Revision 0</a></li>
  <li><a href="#0.2">Revision 1</a></li>
  <li><a href="#0.3">Revision 2</a></li>
  </ul>
<li><a href="#1.0">Introduction</a></li>
<li><a href="#2.0">Recommended for Immediate Adoption</a></li>
<li><a href="#3.0">Remove Support for the Adaptable Function Protocol</a></li>
  <ul>
  <li><a href="#3.1">Remove the Classic <tt>not1</tt> and <tt>not2</tt> Negators</a></li>
  <li><a href="#3.2">Remove the <tt>typedef</tt>s that Support Adaptable Functions</a></li>
  <li><a href="#3.3">Allow Vendors to Support Customers</a></li>
  <li><a href="#3.4">Precedents for Immediate Removal</a></li>
  </ul>
<li><a href="#4.0">Future Extensions</a></li>
  <ul>
  <li><a href="#4.1"><tt>reference_wrapper</tt> for Incomplete Types</a></li>
  <li><a href="#4.2">Negated <tt>bind</tt> Expressions</a></li>
  </ul>
<li><a href="#5.0">Established Experience</a></li>
<li><a href="#6.0">Proposed Wording</a></li>
<li><a href="#7.0">References</a></li>
</ul>


<h2><a name="0.0">Revision History</a></h2>

<h3><a name="0.1">Revision 0</a></h3>
<p>
Original version of the paper for the 2015 pre-Kona mailing.
</p>

<h3><a name="0.2">Revision 1</a></h3>
<p>
Revised to follow
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0090r0.htm">P0090R0</a>,
eliminating <i>weak result type</i> and <tt>result_type</tt>, and adding
compatibility clauses to Annex C.
</p>
<p>
Additional future work item for <tt>std::reference_wrapper</tt>.
</p>
<p>
Established precedent for removing features from the standard without a
period of deprecation.
</p>

<h3><a name="0.3">Revision 2</a></h3>
<p>
LEWG review recommended we should keep the <tt>result_type</tt> typedef for
<tt>std::function</tt>.
</p>
<p>
At LWG recommendation, renamed the <tt>fn</tt> term used in the specification
of <tt>not_fn</tt> with <tt>g</tt>, the same name used in the <tt>bind</tt>
specification, to minimize confusion with the term <tt>fd</tt> used in the
same paragraphs.
</p>


<h2><a name="1.0">Introduction</a></h2>
<p>
This paper recommends moving the <tt>not_fn</tt> function binder immediately
out of Library Fundamentals 2 TS, into the C++17 Working paper.  There are no
parts of the Fundamentals TS that depend on this new component, and it serves a
bigger purpose in the main standard, allowing the deprecation and removal of
the last of the legacy function binder APIs.  It further recommends removing
any remaining infrastructure to support the C++98 adaptable function binder
protocol, that was mostly removed at the 2014 Urbana meeting.  </p>
<p>
In the same mailing as revision 0 of this paper, Stephan Lavavej proposed
removing the same typedefs, along with the <i>weak result type</i> wording that
completed support for the deprecated (and removed) binders.  This paper agrees
with that direction and merges his wording to form a single, votable paper.
Stephan's proposal remains available if the committee prefer to remove the
binder components without (yet) adopting the <tt>not_fn</tt> replacement.
</p>


<h2><a name="2.0">Recommendation for Immediate Adoption</a></h2>
<p>
The function template <tt>not_fn</tt> is first proposed by Tomasz Kamiński for
Library Fundamentals 2, and so has not yet been published.  However, there is
extensive experience of this feature through the Boost library.  The main
reason cited for putting this into Fundamentals 2, rather than directly into
C++17, was to give users early access to the feature.  However, we are already
seeing new C++17 library features available in the main standard library
distributions, typically guarded by an experimental C++17 build mode flag.
</p>
<p>
The benefit of adopting this library directly into the C++ Standard is that it
is the necessary missing component to allow us to deprecate the legacy negator
types, <tt>unary_negate</tt> and <tt>binary_negate</tt>, and the factory
functions <tt>not1</tt> and <tt>not2</tt>.  These are the last two library
components that depend on the adaptable function protocol of embedding typedefs
in functor classes to support adaption.  The remaining facilities such as
<tt>bind1st</tt> have already been removed, following their deprecation in
C++11, and adopting <tt>not_fn</tt> would allow us to deprecate, and ultimately
remove, this final legacy.
</p>


<h2><a name="3.0">Remove Support for the Adaptable Function Protocol</a></h2>

<h3><a name="3.1">Remove the Classic <tt>not1</tt> and <tt>not2</tt> Negators</a></h3>
<p>
Traditionally we would start a long deprecation process before removing
supported library features such as <tt>not1</tt> and <tt>not2</tt>.  However,
this paper will argue that we should go further and actively remove them from
the proposed C++17 standard, once the <tt>not_fn</tt> replacement is available,
along with the adaptable functors have already been removed from the working
paper.
</p>
<p>
The list of references at the end of this paper shows a number of other
deprecated features targeted for removal in C++17, suggesting this would be an
ideal time to perform cleanup, taking any hit of breaking compatibility with
older code in one transition, rather than making each new version of the
standard a risk.
</p>

<h3><a name="3.2">Remove the <tt>typedef</tt>s that Support Adaptable Functions</a></h3>
<p>
Once the last of the classic binders are removed, then all of the support
machinery created only for them should also be removed.  That means removing
all of the <tt>argument_type</tt>, <tt>first_argument_type</tt>, and
<tt>second_argument_type</tt> typedefs in the standard library.
</p>
<p>
Note that the adaptable function protocol no longer functions as well when it
was originally designed, due to the addition of new language features and
libraries, such as lambda expressions, &quot;diamond&quot; functors, and more.
This is not due to a lack of effort, but simply that it is not possible to have
a unique set of typedefs for some of these types, such as polymorphic lambda
objects.  However, we do pay a cost for retaining support elsewhere in the
library, due to the awkward conditionally defined member typedefs in several
components, such as <tt>std::function</tt> wrapping a function type with
<em>exactly</em> one or two parameters, or similarly for
<tt>std::reference_wrapper</tt> for function references of <em>exactly</em> one
or two arguments.
</p>
<p>
The original version of this paper recommended <em>retaining</em> the
<tt>result_type</tt> typedefs under the mistaken impression they were part of
the <i>INVOKE</i> protocol.  Further research shows that link was severed back
in 2007 with the adoption of
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2194.html">N2194</a>
which specified <tt>result_of</tt> entirely in terms of <tt>decltype</tt>, and
so removing the link between <i>bind</i>-expressions and <tt>result_of</tt>
when using <tt><i>INVOKE</i></tt>.  With the subsequent removal of the
deprecated function binders, and the proposed removal of the classic negators
in this paper, there is no further use of weak result types in the standard
library, other than defining them.  Therefore, I agree with Stephan Lavavej in
paper
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0090r0.htm">P0090R0</a>
and recommend the removal <i>weak result type</i> and related uses of
<tt>result_type</tt> from the standard library too.
</p>
<p>
One final wrinkle is that, based on review in Library Evolution, and feedback
from those still actively using the feature, the <tt>result_type</tt> typedef
should be retained for the two class templates <tt>std::hash</tt> and
<tt>std::function</tt>.  After further review, noting that the <tt>Hash</tt>
concept for user-supplied hashing functors makes no requirement for
<tt>result_type</tt>, it was recommended that <tt>result_type</tt> be retained
for only <tt>std::function</tt>.
</p>

<h3><a name="3.3">Allow Vendors to Support Customers</a></h3>
<p>
Library vendors will often choose to continue supporting customers using
previous library features long after the standard has removed them, especially
if they support multiple versions of the standard through the same distribution.
Stephan proposed adding a subsection to clause 17 reserving certain names for
use by <em>previous</em> standards.  This continues to reserve those names for
use by the library, meaning that users are not permitted to start using these
names as macros.  It also allows vendors to remove these identifiers at a time
of their choosing, rather than immediately on the release of the new standard.
This will mitigate the previous removal of deprecated features like
<tt>auto_ptr</tt>.
</p>
<p>
This paper adopts Stephan's wording with the minor alteration that continued
support of the adaptable function typedefs is unspecified, rather than
implementation defined.  Stephan has a preference for his original wording,
while Alisdair is concerned about mandating documentation for something outside
the standard, so there should be at least some explicit LEWG guidance on which
direction is preferred.
</p>


<h3><a name="3.4">Precedents for Immediate Removal</a></h3>
<p>
Removing a feature directly from the standard without a period of deprecation
is unusual, but not without precedent.  C++11 removed exported templates and
the original meaning of the keyword <tt>auto</tt>.  C++14 removed <tt>gets</tt>
and the implicit <tt>const</tt> on <tt>constexpr</tt> functions.  The C++17
working draft has already removed support for trigraphs.
</p>


<h2><a name="4.0">Future Extensions</a></h2>

<h3><a name="4.1"><tt>reference_wrapper</tt> for Incomplete Types</a></h3>
<p>
Removing the <tt>result_type</tt> typedefs would enable support for incomplete
types in <tt>reference_wrapper</tt>.  That is not possible today due to the
need to look inside the template type parameter to sniff out the presence of a
weak result type, or any of the other nested typedefs.  The key difference to
the current proposal is that <tt>reference_wrapper</tt> would be actively
prohibited from adding the previous (conditional) typedefs for compatibility
purposes otherwise permitted by the proposed zombie-names clause.
Additionally, <b>17.6.4.8 [res.on.functions]</b>/2.5 still holds, making it
clear that we would be required to call out this support for
<tt>reference_wrapper</tt>.  In the meantime, implementations would be free to
document and extend this guarantee as a conforming extension.
</p>
<p>
Adopting this suggestion would enable code like the following, that is
currently ill-formed if the template type parameters are incomplete when
instantiated:
</p>
<blockquote><pre>
template&lt;typename T, typename U&gt;
auto my_tie(T&amp; t, U&amp; u) {
    return std::make_tuple(ref(t), ref(u));
}
</pre></blockquote>

<h3><a name="4.2">Negated <tt>bind</tt> Expressions</a></h3>
<p>
Another feature of the Boost library that contributed the original design for
<tt>not_fn</tt> is an expansion of the <tt>bind</tt> language to return a bind
expression that negates its result when called as
<tt>!bind(a1, a2, ..., aN)</tt>.
</p>
<p>
While this feature is desirable, it has not yet been through the LEWG process,
and is slightly trickier to word than implement as the result of a 'bind'
expression is unspecified, and the interaction works by providing an
<tt>operator!</tt> overload for the unspecified bind-object type.  Therefore,
this is left as an extension to be proposed for the Library Fundamentals 3 TS.
</p>


<h2><a name="5.0">Established Experience</a></h2>
<p>
The <tt>not_fn</tt> library, and its interaction with <tt>bind</tt>, have been
popular parts of the Boost library distribution for over a decade now.  The
interface and specification are mature.
</p>


<h2><a name="6.0">Proposed Wording</a></h2>


Insert a new section under <b>17.6.4.3 [reserved.names]</b>, between
<b>17.6.4.3.1 [macro.names]</b> and <b>17.6.4.3.2 [extern.names]</b>:

<blockquote>
<h3><ins>17.6.4.3.x Zombie names [zombie.names]</ins></h3>

<p><ins>
In namespace <tt>std</tt>, the following names are reserved for previous
standardization: <tt>auto_ptr</tt>, <tt>bind1st</tt>, <tt>bind2nd</tt>,
<tt>binder1st</tt>, <tt>binder2nd</tt>, <tt>mem_fun</tt>, <tt>mem_fun_ref</tt>,
<tt>mem_fun_t</tt>, <tt>mem_fun1_t</tt>, <tt>mem_fun_ref_t</tt>,
<tt>mem_fun1_ref_t</tt>, <tt>const_mem_fun_t</tt>, <tt>const_mem_fun1_t</tt>,
<tt>const_mem_fun_ref_t</tt>, <tt>const_mem_fun1_ref_t</tt>, <tt>not1</tt>,
<tt>not2</tt>, <tt>unary_negate</tt>, <tt>binary_negate</tt>, <tt>ptr_fun</tt>,
<tt>pointer_to_unary_function</tt>, <tt>pointer_to_binary_function</tt>,
<tt>random_shuffle</tt>, <tt>unary_function</tt>, and <tt>binary_function</tt>.
</ins></p>
<p><ins>
It is unspecified whether function objects in the C++ standard library
additionally provide the following typedefs: <tt>result_type</tt>,
<tt>argument_type</tt>, <tt>first_argument_type</tt>, and
<tt>second_argument_type</tt>.
</ins></p>
</blockquote>

<p>
Amend the <tt>&lt;function&gt;</tt> header synopsis in <b>20.0p2 [function.objects]</b>:
</p>

<blockquote>
<p><pre>
  <del><i>// 20.9.9, negators:</i></del>
  <del>template &lt;class Predicate&gt; class unary_negate;</del>
  <del>template &lt;class Predicate&gt;</del>
    <del>constexpr unary_negate&lt;Predicate&gt; not1(const Predicate&amp;);</del>
  <del>template &lt;class Predicate&gt; class binary_negate;</del>
  <del>template &lt;class Predicate&gt;</del>
    <del>constexpr binary_negate&lt;Predicate&gt; not2(const Predicate&amp;);</del>

  <ins><i>// 20.9.9, Function template not_fn</i></ins>
  <ins>template &lt;class F&gt; <i>unspecified</i> not_fn(F&amp;&amp; f);</ins>
</pre></p>
</blockquote>


<p>
Strike the <tt>result_type</tt>, <tt>first_argument_type</tt>, and
<tt>second_argument_type</tt> typedefs from <b>20.8.2.4 [util.smartptr.ownerless]</b>.
</p>

<blockquote>
<h3>20.8.2.4 Class template <tt>owner_less</tt>   [util.smartptr.ownerless]</h3>
<p>
1 The class template owner_less allows ownership-based mixed comparisons of
shared and weak pointers.
</p>
<blockquote><pre>
namespace std {
  template&lt;class T&gt; struct owner_less;

  template&lt;class T&gt; struct owner_less&lt;shared_ptr&lt;T&gt; &gt; {
    <del>typedef bool result_type;</del>
    <del>typedef shared_ptr&lt;T&gt; first_argument_type;</del>
    <del>typedef shared_ptr&lt;T&gt; second_argument_type;</del>
    bool operator()(shared_ptr&lt;T&gt; const&amp;, shared_ptr&lt;T&gt; const&amp;) const;
    bool operator()(shared_ptr&lt;T&gt; const&amp;, weak_ptr&lt;T&gt; const&amp;) const;
    bool operator()(weak_ptr&lt;T&gt; const&amp;, shared_ptr&lt;T&gt; const&amp;) const;
  };

  template&lt;class T&gt; struct owner_less&lt;weak_ptr&lt;T&gt; &gt; {
    <del>typedef bool result_type;</del>
    <del>typedef weak_ptr&lt;T&gt; first_argument_type;</del>
    <del>typedef weak_ptr&lt;T&gt; second_argument_type;</del>
    bool operator()(weak_ptr&lt;T&gt; const&amp;, weak_ptr&lt;T&gt; const&amp;) const;
    bool operator()(shared_ptr&lt;T&gt; const&amp;, weak_ptr&lt;T&gt; const&amp;) const;
    bool operator()(weak_ptr&lt;T&gt; const&amp;, shared_ptr&lt;T&gt; const&amp;) const;
  };
}
</pre></blockquote>
</blockquote>

<p>
Strike the last note in 20.9p5 [function.objects]:
</p>

<blockquote>
<p><del>
5 [<i>Note:</i> To enable adaptors and other components to manipulate function
objects that take one or two arguments many of the function objects in this
clause 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. — <i>end
note</i> ]
</del></p>
</blockquote>


<p>
Strike the definition of <i>weak result type</i> from 20.9.2:
</p>

<blockquote>
<h3>20.9.2 Requirements [func.require]</h3>
<ol>
  <li>Define <tt><i>INVOKE</i> (f, t1, t2, ..., tN)</tt> as follows:</li>
  <ol>
    <li><tt>(t1.*f)(t2, ..., tN)</tt> when <tt>f</tt> is a pointer to a member function of
        a class <tt>T</tt> and <tt>t1</tt> is an object of type <tt>T</tt> or a reference to
        an object of type <tt>T</tt> or a reference to an object of a type derived from
        <tt>T</tt>;</li>
    <li><tt>((*t1).*f)(t2, ..., tN)</tt> when <tt>f</tt> is a pointer to a member function of
        a class <tt>T</tt> and <tt>t1</tt> is not one of the types described in the previous
        item;</li>
    <li><tt>t1.*f</tt> when N == 1</tt> and <tt>f</tt> is a pointer to member data of a class
        <tt>T</tt> and <tt>t1</tt> is an object of type <tt>T</tt> or a reference to an object
        of type <tt>T</tt> or a reference to an object of a type derived from <tt>T</tt>;</li>
    <li><tt>(*t1).*f</tt> when <tt>N == 1</tt> and <tt>f</tt> is a pointer to member data of a
        class <tt>T</tt> and <tt>t1</tt> is not one of the types described in the previous
        item;</li>
    <li><tt>f(t1, t2, ..., tN)</tt> in all other cases.</li>
  </ol>

  <li>Define <tt><i>INVOKE</i> (f, t1, t2, ..., tN, R)</tt> as
      <tt>static_cast&lt;void&gt;(<i>INVOKE</i> (f, t1, t2, ..., tN))</tt> if
      <tt>R</tt> is <i>cv</i> <tt>void</tt>, otherwise
      <tt><i>INVOKE</i> (f, t1, t2, ..., tN)</tt> implicitly converted to <tt>R</tt>.</li>

  <li><del>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):</del></li>
  <ol>
    <li><del>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>;</del></li>
    <li><del>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>;</del></li>
    <li><del>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>;</del></li>
    <li><del>otherwise <tt>result_type</tt> shall not be defined.</del></li>
  </ol>
  <li>
Every call wrapper (20.9.1) shall be <tt>MoveConstructible</tt>. A <i>simple
call wrapper</i> is a call wrapper that is <tt>CopyConstructible</tt> and
<tt>CopyAssignable</tt> and whose copy constructor, move constructor, and
assignment operator do not throw exceptions. A <i>forwarding call wrapper</i>
is a call wrapper that can be called with an arbitrary argument list and
delivers the arguments to the wrapped callable object as references.  This
forwarding step shall ensure that rvalue arguments are delivered as rvalue
references and lvalue arguments are delivered as lvalue references.
[<i>Note:</i> In a typical implementation forwarding call wrappers have an
overloaded function call operator of the form
<blockquote><pre>
template&lt;class... UnBoundArgs&gt;
R operator()(UnBoundArgs&amp;&amp;... unbound_args) <i>cv-qual</i>;
</pre></blockquote>
— <i>end note</i> ]
  </li>
</ol>

</blockquote>


<p>
Simplify the definition of <tt>reference_wrapper</tt>:
</p>

<blockquote>
<h3>20.9.4 Class template reference_wrapper   [refwrap]</h3>
<p><pre><blockquote>
namespace std {
  template &lt;class T&gt; class reference_wrapper {
  public :
    <i>// types</i>
    typedef T type;
    <del>typedef <i>see below</i> result_type;              <i>// not always defined</i></del>
    <del>typedef <i>see below</i> argument_type;            <i>// not always defined</i></del>
    <del>typedef <i>see below</i> first_argument_type;      <i>// not always defined</i></del>
    <del>typedef <i>see below</i> second_argument_type;     <i>// not always defined</i></del>

    <i>// construct/copy/destroy</i>
    reference_wrapper(T&amp;) noexcept;
    reference_wrapper(T&amp;&amp;) = delete; <i>// do not bind to temporary objects</i>
    reference_wrapper(const reference_wrapper&amp; x) noexcept;

    <i>// assignment</i>
    reference_wrapper&amp; operator=(const reference_wrapper&amp; x) noexcept;

    <i>// access</i>
    operator T&amp; () const noexcept;
    T&amp; get() const noexcept;

    <i>// invocation</i>
    template &lt;class... ArgTypes&gt;
    result_of_t&lt;T&amp;(ArgTypes&amp;&amp;...)&gt;
    operator() (ArgTypes&amp;&amp;...) const;
  };
}
</blockquote></pre></p>


<p>
1 <tt>reference_wrapper&lt;T&gt;</tt> is a <tt>CopyConstructible</tt> and
<tt>CopyAssignable</tt> wrapper around a reference to an object or function of
type <tt>T</tt>.
</p>
<p>
2 <tt>reference_wrapper&lt;T&gt;</tt> shall be a trivially copyable type (3.9).
</p>
<p><del>
3 <tt>reference_wrapper&lt;T&gt;</tt> has a weak result type (20.9.2). If
<tt>T</tt> is a function type, <tt>result_type</tt> shall be a synonym for the
return type of <tt>T</tt>.
</del></p>
<p><del>
4 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:
</del></p>
<p><del>
(4.1) — a function type or a pointer to function type taking one argument of
type <tt>T1</tt>
</del></p>
<p><del>
(4.2) — 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>
</del></p>
<p><del>
(4.3) — 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>.
</del></p>
<p><del>
5 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:
</del></p>
<p><del>
(5.1) — a function type or a pointer to function type taking two arguments of
types <tt>T1</tt> and <tt>T2</tt> </del></p>
<p><del>
(5.2) — 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>
</del></p>
<p><del>
(5.3) — 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>.
</del></p>
</blockquote>


<p>
Strike the <tt>result_type</tt>, <tt>argument_type</tt>,
<tt>first_argument_type</tt>, and <tt>second_argument_type</tt> typedefs from
<b>20.9.5 [arithmetic.operations]</b>.
</p>

<blockquote>
<h3>20.9.5 Arithmetic operations [arithmetic.operations]</h3>
<p>
1 The library provides basic function object classes for all of the arithmetic
operators in the language (5.6, 5.7).  </p>
<blockquote><pre>
template &lt;class T = void&gt; struct plus {
  constexpr T operator()(const T&amp; x, const T&amp; y) const;
  <del>typedef T first_argument_type;</del>
  <del>typedef T second_argument_type;</del>
  <del>typedef T result_type;</del>
};
</pre></blockquote>
<p>
2 <tt>operator()</tt> returns <tt>x + y</tt>.
</p>
<blockquote><pre>
template &lt;class T = void&gt; struct minus {
  constexpr T operator()(const T&amp; x, const T&amp; y) const;
  <del>typedef T first_argument_type;</del>
  <del>typedef T second_argument_type;</del>
  <del>typedef T result_type;</del>
};
</pre></blockquote>
<p>
3 <tt>operator()</tt> returns <tt>x - y</tt>.
</p>
<blockquote><pre>
template &lt;class T = void&gt; struct multiplies {
  constexpr T operator()(const T&amp; x, const T&amp; y) const;
  <del>typedef T first_argument_type;</del>
  <del>typedef T second_argument_type;</del>
  <del>typedef T result_type;</del>
};
</pre></blockquote>
<p>
4 <tt>operator()</tt> returns <tt>x * y</tt>.
</p>
<blockquote><pre>
template &lt;class T = void&gt; struct divides {
  constexpr T operator()(const T&amp; x, const T&amp; y) const;
  <del>typedef T first_argument_type;</del>
  <del>typedef T second_argument_type;</del>
  <del>typedef T result_type;</del>
};
</pre></blockquote>
<p>
5 <tt>operator()</tt> returns <tt>x / y</tt>.
</p>
<blockquote><pre>
template &lt;class T = void&gt; struct modulus {
  constexpr T operator()(const T&amp; x, const T&amp; y) const;
  <del>typedef T first_argument_type;</del>
  <del>typedef T second_argument_type;</del>
  <del>typedef T result_type;</del>
};
</pre></blockquote>
<p>
6 <tt>operator()</tt> returns <tt>x % y</tt>.
</p>
<blockquote><pre>
template &lt;class T = void&gt; struct negate {
  constexpr T operator()(const T&amp; x) const;
  <del>typedef T argument_type;</del>
  <del>typedef T result_type;</del>
};
</pre></blockquote>
<p>
7 <tt>operator()</tt> returns <tt>-x</tt>.
</p>
</blockquote>


<p>
Strike the <tt>result_type</tt>, <tt>first_argument_type</tt>, and
<tt>second_argument_type</tt> typedefs from <b>20.9.6 [comparisons]</b>.
</p>

<blockquote>

<h3>20.9.6 Comparisons   [comparisons]</h3>
<p>
1 The library provides basic function object classes for all of the comparison
operators in the language (5.9, 5.10).  </p>
<blockquote><pre>
template &lt;class T = void&gt; struct equal_to {
  constexpr bool operator()(const T&amp; x, const T&amp; y) const;
  <del>typedef T first_argument_type;</del>
  <del>typedef T second_argument_type;</del>
  <del>typedef bool result_type;</del>
};
</pre></blockquote>
<p>
2 <tt>operator()</tt> returns <tt>x == y</tt>.
</p>

<blockquote><pre>
template &lt;class T = void&gt; struct not_equal_to {
  constexpr bool operator()(const T&amp; x, const T&amp; y) const;
  <del>typedef T first_argument_type;</del>
  <del>typedef T second_argument_type;</del>
  <del>typedef bool result_type;</del>
};
</pre></blockquote>
<p>
3 <tt>operator()</tt> returns <tt>x != y</tt>.
</p>

<blockquote><pre>
template &lt;class T = void&gt; struct greater {
  constexpr bool operator()(const T&amp; x, const T&amp; y) const;
  <del>typedef T first_argument_type;</del>
  <del>typedef T second_argument_type;</del>
  <del>typedef bool result_type;</del>
};
</pre></blockquote>
<p>
4 <tt>operator()</tt> returns <tt>x &gt; y</tt>.
</p>

<blockquote><pre>
template &lt;class T = void&gt; struct less {
  constexpr bool operator()(const T&amp; x, const T&amp; y) const;
  <del>typedef T first_argument_type;</del>
  <del>typedef T second_argument_type;</del>
  <del>typedef bool result_type;</del>
};
</pre></blockquote>
<p>
5 <tt>operator()</tt> returns <tt>x &lt; y</tt>.
</p>

<blockquote><pre>
template &lt;class T = void&gt; struct greater_equal {
  constexpr bool operator()(const T&amp; x, const T&amp; y) const;
  <del>typedef T first_argument_type;</del>
  <del>typedef T second_argument_type;</del>
  <del>typedef bool result_type;</del>
};
</pre></blockquote>
<p>
6 <tt>operator()</tt> returns <tt>x &gt;= y</tt>.
</p>

<blockquote><pre>
template &lt;class T = void&gt; struct less_equal {
  constexpr bool operator()(const T&amp; x, const T&amp; y) const;
  <del>typedef T first_argument_type;</del>
  <del>typedef T second_argument_type;</del>
  <del>typedef bool result_type;</del>
};
</pre></blockquote>
<p>
7 <tt>operator()</tt> returns <tt>x &lt;= y</tt>.
</p>
</blockquote>


<p>
Strike the <tt>result_type</tt>, <tt>argument_type</tt>,
<tt>first_argument_type</tt>, and <tt>second_argument_type</tt> typedefs from
<b>20.9.7 [logical.operations]</b>.
</p>

<blockquote>
<h3>20.9.7 Logical operations [logical.operations]</h3>
<p>
1 The library provides basic function object classes for all of the logical
operators in the language (5.14, 5.15, 5.3.1).
</p>
<blockquote><pre>
template &lt;class T = void&gt; struct logical_and {
  constexpr bool operator()(const T&amp; x, const T&amp; y) const;
  <del>typedef T first_argument_type;</del>
  <del>typedef T second_argument_type;</del>
  <del>typedef bool result_type;</del>
};
</pre></blockquote>
<p>
2 <tt>operator()</tt> returns <tt>x &amp;&amp; y</tt>.
</p>

<blockquote><pre>
template &lt;class T = void&gt; struct logical_or {
  constexpr bool operator()(const T&amp; x, const T&amp; y) const;
  <del>typedef T first_argument_type;</del>
  <del>typedef T second_argument_type;</del>
  <del>typedef bool result_type;</del>
};
</pre></blockquote>
<p>
3 <tt>operator()</tt> returns <tt>x || y</tt>.
</p>

<blockquote><pre>
template &lt;class T = void&gt; struct logical_not {
  constexpr bool operator()(const T&amp; x) const;
  <del>typedef T argument_type;</del>
  <del>typedef bool result_type;</del>
};
</pre></blockquote>
<p>
4 <tt>operator()</tt> returns <tt>!x</tt>.
</p>
</blockquote>


<p>
Strike the <tt>result_type</tt>, <tt>argument_type</tt>,
<tt>first_argument_type</tt>, and <tt>second_argument_type</tt> typedefs from
<b>20.9.8 [bitwise.operations]</b>.
</p>

<blockquote>
<h3>20.9.8 Bitwise operations [bitwise.operations]</h3>
<p>
1 The library provides basic function object classes for all of the bitwise
operators in the language (5.11, 5.13, 5.12, 5.3.1).
</p>
<blockquote><pre>
template &lt;class T = void&gt; struct bit_and {
  constexpr T operator()(const T&amp; x, const T&amp; y) const;
  <del>typedef T first_argument_type;</del>
  <del>typedef T second_argument_type;</del>
  <del>typedef T result_type;</del>
};
</pre></blockquote>
<p>
2 <tt>operator()</tt> returns <tt>x &amp; y</tt>.
</p>

<blockquote><pre>
template &lt;class T = void&gt; struct bit_or {
  constexpr T operator()(const T&amp; x, const T&amp; y) const;
  <del>typedef T first_argument_type;</del>
  <del>typedef T second_argument_type;</del>
  <del>typedef T result_type;</del>
};
</pre></blockquote>
<p>
3 <tt>operator()</tt> returns <tt>x | y</tt>.
</p>

<blockquote><pre>
template &lt;class T = void&gt; struct bit_xor {
  constexpr T operator()(const T&amp; x, const T&amp; y) const;
  <del>typedef T first_argument_type;</del>
  <del>typedef T second_argument_type;</del>
  <del>typedef T result_type;</del>
};
</pre></blockquote>
<p>
4 <tt>operator()</tt> returns <tt>x ^ y</tt>.
</p>

<blockquote><pre>
template &lt;class T = void&gt; struct bit_not {
  constexpr bool operator()(const T&amp; x) const;
  <del>typedef T argument_type;</del>
  <del>typedef T result_type;</del>
};
</pre></blockquote>
<p>
5 <tt>operator()</tt> returns <tt>~x</tt>.
</p>
</blockquote>


<p>
Replace subclause <b>20.9.9 [negators]</b> with a new subclause <b>20.9.9
[func.not_fn]</b>, copying everything from the Library Fundamentals 2 TS other
than the struck-out note:
</p>

<blockquote>
<h3><del>20.9.9 Negators [negators]</del></h3>
<p><del>
1 Negators <tt>not1</tt> and <tt>not2</tt> take a unary and a binary predicate,
respectively, and return their complements (5.3.1).
</del></p>

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

<p><del>
2 <tt>operator()</tt> returns <tt>!pred(x)</tt>.
</del></p>

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

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

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

<p><del>
4 <tt>operator()</tt> returns <tt>!pred(x,y)</tt>.
</del></p>

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

<p><del>
5 <i>Returns:</i> <tt>binary_negate&lt;Predicate&gt;(pred)</tt>.
</del></p>

<h3><ins>20.9.9 Function template not_fn [func.not_fn]</ins></h3>
<p><pre><blockquote>
<ins>template &lt;class F&gt; <i>unspecified</i> not_fn(F&amp;&amp; f);</ins>
</blockquote></pre></p>
<p><ins>
1 In the text that follows:
</ins><p>
<ul>
<li><ins><tt>FD</tt> is the type <tt>decay_t&lt;F&gt;</tt>,</li></ins>
<li><ins><tt>fd</tt> is an lvalue of type <tt>FD</tt> constructed from <tt>std::forward&lt;F&gt;(f)</tt>,</li></ins>
<li><ins><tt>g</tt> is a forwarding call wrapper created as a result of <tt>not_fn(f)</tt>,</li></ins>
</ul>

<p><ins>
2 <i>Requires:</i>
<tt>is_constructible&lt;FD, F&gt;::value</tt> shall be <tt>true</tt>.
<tt>fd</tt> shall be a callable object (§20.9.1).
</ins></p>
<p><ins>
3 <i>Returns:</i>
A forwarding call wrapper <tt>g</tt> such that the expression
<tt>g(a1, a2, ..., aN)</tt> is equivalent to
<tt>!<i>INVOKE</i>(fd, a1, a2, ..., aN)</tt> (§20.9.2).
</ins></p>
<p><ins>
4 <i>Throws:</i>
Nothing unless the construction of <tt>fd</tt> throws an exception.
</ins></p>
<p><ins>
5 <i>Remarks:</i>
The return type shall satisfy the requirements of <tt>MoveConstructible</tt>.
If <tt>FD</tt> satisfies the requirements of <tt>CopyConstructible</tt>, then
the return type shall satisfy the requirements of <tt>CopyConstructible</tt>.
[ <i>Note:</i> This implies that <tt>FD</tt> is <tt>MoveConstructible</tt>. —
<i>end note</i> ]
</ins></p>
<p><del>
[ <i>Note:</i> Function template <tt>not_fn</tt> can usually provide a better
solution than using the negators <tt>not1</tt> and <tt>not2</tt> — <i>end
note</i> ]
</del></p>
</blockquote>


<p>
Remove the weak result type from the type returns from bind expressions in
<b>20.9.10.3 [func.bind.bind]</b>:
</p>

<blockquote>
3 <i>Returns:</i> A forwarding call wrapper <tt>g</tt> <del>with a weak result
type</del> (20.9.2). The effect of <tt>g(u1, u2, ..., uM)</tt> shall be
<tt><i>INVOKE</i>(fd, std::forward&lt;V1&gt;(v1), std::forward&lt;V2&gt;(v2), ..., std::forward&lt;VN&gt;(vN), result_of_t&lt;FD <i>cv</i> &amp; (V1, V2, ..., VN)&gt;)</tt>,
where <i>cv</i> represents the <i>cv</i>-qualifiers of <tt>g</tt> and the
values and types of the bound arguments <tt>v1</tt>, <tt>v2</tt>, ...,
<tt>vN</tt> are determined as specified below. The copy constructor and move
constructor of the forwarding call wrapper shall throw an exception if and only
if the corresponding constructor of <tt>FD</tt> or of any of the types
<tt>T<sub>i</sub>D</tt> throws an exception.
</blockquote>


<p>
Remove the <tt>result_type</tt> member from the type returned by bind
expressions with user-specified return types in <b>20.9.10.3
[func.bind.bind]</b>:
</p>

<blockquote>
7 <i>Returns:</i> A forwarding call wrapper <tt>g</tt> <ins>(20.9.2)</ins><del>
with a nested type <tt>result_type</tt> defined as a synonym for <tt>R</tt></del>.
The effect of <tt>g(u1, u2, ..., uM)</tt> shall be
<tt><i>INVOKE</i>(fd, std::forward&lt;V1&gt;(v1), std::forward&lt;V2&gt;(v2), ..., std::forward&lt;VN&gt;(vN), R)</tt>,
where the values and types of the bound arguments <tt>v1, v2, ..., vN</tt> are
determined as specified below.  The copy constructor and move constructor of
the forwarding call wrapper shall throw an exception if and only if the
corresponding constructor of <tt>FD</tt> or of any of the types
<tt>T<sub>i</sub>D</tt> throws an exception.
</blockquote>


<p>
Strike the unnecessary typedefs from the unspecified return-type of
<tt>mem_fn</tt>:
</p>

<blockquote>
<h3>20.9.11 Function template <tt>mem_fn</tt>   [func.memfn]</h3>
<blockquote><pre>
template&lt;class R, class T&gt; <i>unspecified</i> mem_fn(R T::* pm);
</pre></blockquote>
<p>
1 <i>Returns:</i> A simple call wrapper (20.9.1) <tt>fn</tt> such that the
expression <tt>fn(t, a2, ..., aN)</tt> is equivalent to
<tt><i>INVOKE</i> (pm, t, a2, ..., aN)</tt> (20.9.2). <del><tt>fn</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.</del>
</p>
<p><del>
2 The simple call wrapper 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.
</del></p>
<p><del>
3 The simple call wrapper 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.
</del></p>
<p>
4 <i>Throws:</i> Nothing.
</p>
</blockquote>


<p>
Strike the relevant typedefs from the class definition of <tt>function</tt>:
</p>

<blockquote>
<h3>20.9.12.2 Class template function   [func.wrap.func]</h3>
<p><pre><blockquote>
namespace std {
template&lt;class&gt; class function; <i>// undefined</i>
template&lt;class R, class... ArgTypes&gt;
class function&lt;R(ArgTypes...)&gt; {
public:
  typedef R result_type;
  <del>typedef T1 argument_type;          <i>// only if sizeof...(ArgTypes) == 1 and</i></del>
                                     <del><i>// the type in ArgTypes is T1</i></del>
  <del>typedef T1 first_argument_type;    <i>// only if sizeof...(ArgTypes) == 2 and</i></del>
                                     <del><i>// ArgTypes contains T1 and T2</i></del>
  <del>typedef T2 second_argument_type;   <i>// only if sizeof...(ArgTypes) == 2 and</i></del>
                                     <del><i>// ArgTypes contains T1 and T2</i></del>

  <i>// further details elided...</i>
};
</blockquote></pre></p>
</blockquote>


<p>
Strike bullet (1.3), on the definition of standard <tt>hash</tt> functors:
</p>

<blockquote>
<h3>20.9.13 Class template hash  [unord.hash]</h3>
<p>
1 The unordered associative containers defined in 23.5 use specializations of
the class template <tt>hash</tt> as the default hash function. 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:
</p>
<p>
(1.1) — satisfy the <tt>Hash</tt> requirements (17.6.3.4), with <tt>Key</tt> as
the function call argument type, the <tt>DefaultConstructible</tt> requirements
(Table 19), the <tt>CopyAssignable</tt> requirements (Table 23),
</p>
<p>
(1.2) — be swappable (17.6.3.2) for lvalues,
</p>
<p><del>
(1.3) — 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,
</del></p>
<p>
(1.4) — satisfy the requirement that if <tt>k1 == k2</tt> is true,
<tt>h(k1) == h(k2)</tt> is also true, where <tt>h</tt> is an object of type
<tt>hash&lt;Key&gt;</tt> and <tt>k1</tt> and <tt>k2</tt> are objects of type
<tt>Key</tt>;
</p>
<p>
(1.5) — satisfy the requirement that the expression <tt>h(k)</tt>, where
<tt>h</tt> is an object of type <tt>hash&lt;Key&gt;</tt> and <tt>k</tt> is an
object of type <tt>Key</tt>, shall not throw an exception unless
<tt>hash&lt;Key&gt;</tt> is a user-defined specialization that depends on at
least one user-defined type.
</p>
</blockquote>


<p>
Strike the <tt>result_type</tt>, <tt>first_argument_type</tt>, and
<tt>second_argument_type</tt> typedefs from the <tt>value_compare</tt>
member-class of <tt>map</tt> in <b>23.4.4.1 [map.overview]</b>.
</p>

<blockquote>

<h3>23.4.4 Class template <tt>map</tt>              [map]</h3>
<h3>23.4.4.1 Class template <tt>map</tt> overview   [map.overview]</h3>
<blockquote><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:
     <i>// types</i>
     <i>// details elided...</i>

     class value_compare {
     friend class map;
     protected:
       Compare comp;
       value_compare(Compare c) : comp(c) {}
     public:
       <del>typedef bool result_type;</del>
       <del>typedef value_type first_argument_type;</del>
       <del>typedef value_type second_argument_type;</del>
       bool operator()(const value_type&amp; x, const value_type&amp; y) const {
         return comp(x.first, y.first);
       }
    };

    <i>// 23.4.4.2, construct/copy/destroy:</i>
    <i>// remaining details elided...</i>
  };
}
</pre></blockquote>
</blockquote>


<p>
Strike the <tt>result_type</tt>, <tt>first_argument_type</tt>, and
<tt>second_argument_type</tt> typedefs from the <tt>value_compare</tt>
member-class of <tt>multimap</tt> in <b>23.4.5.1 [multimap.overview]</b>.
</p>

<blockquote>

<h3>23.4.5 Class template <tt>multimap</tt>              [multimap]</h3>
<h3>23.4.5.1 Class template <tt>multimap</tt> overview   [multimap.overview]</h3>
<blockquote><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 multimap {
  public:
     <i>// types</i>
     <i>// details elided...</i>

     class value_compare {
     friend class map;
     protected:
       Compare comp;
       value_compare(Compare c) : comp(c) {}
     public:
       <del>typedef bool result_type;</del>
       <del>typedef value_type first_argument_type;</del>
       <del>typedef value_type second_argument_type;</del>
       bool operator()(const value_type&amp; x, const value_type&amp; y) const {
         return comp(x.first, y.first);
       }
    };

    <i>// 23.4.4.2, construct/copy/destroy:</i>
    <i>// remaining details elided...</i>
  };
}
</pre></blockquote>
</blockquote>


<p>
Add a new section under C.4 [diff.cpp14], between <b>C.4.1 [diff.cpp14.lex]</b>
and <b>C.4.2 [diff.cpp14.depr]</b>:
</p>

<blockquote>
<h3><ins>C.4.x Clause 20: general utilities library [diff.cpp14.utilities]</ins></h3>

<p><ins>
<b>Change:</b> The typedefs <tt>result_type</tt>, <tt>argument_type</tt>,
<tt>first_argument_type</tt>, and <tt>second_argument_type</tt> might not be
defined by some function objects.
</ins></p>
<p><ins>
<b>Rationale:</b> Superseded by new features, including <tt>decltype</tt> and
forwarding references.
</ins></p>
<p><ins>
<b>Effect on original feature:</b> Valid C++ 2014 code that uses these typedefs
may fail to compile in this International Standard.
</ins></p>
<br/>
<p><ins>
<b>Change:</b> The class templates <tt>unary_negate</tt> and
<tt>binary_negate</tt> and the function templates <tt>not1</tt> and
<tt>not2</tt> might not be defined.
</ins></p>
<p><ins>
<b>Rationale:</b> Superseded by new features, including generic lambdas and the
function template <tt>not_fn</tt>.
</ins></p>
<p><ins>
<b>Effect on original feature:</b> Valid C++ 2014 code that uses these class
templates and function templates may fail to compile in this International
Standard.
</ins></p>
</blockquote>


<h2><a name="7.0">References</h2>
<ul>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2194.html">N2194</a> decltype for the C++0x Standard Library, Douglas Gregor, Jaakko Järvi</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4076.html">N4076</a> A proposal to add a generalized callable negator, Tomasz Kamiński</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4086">N4086</a> Removing trigraphs??!, Richard Smith</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4168">N4168</a> Removing <tt>auto_ptr</tt>, Billy Baker</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4190">N4190</a> Removing <tt>auto_ptr</tt>, <tt>random_shuffle()</tt>, And Old <tt>&lt;functional&gt;</tt> Stuff, Stephan T. Lavavej</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0001r0.html">P0001R0</a> Remove Deprecated Use of the <tt>register</tt> Keyword, Alisdair Meredith</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0002r0.html">P0002R0</a> Remove Deprecated <tt>operator++(bool)</tt>, Alisdair Meredith</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0003r0.html">P0003R0</a> Remove Deprecated Exception Specifications from C++17, Alisdair Meredith</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0004r0.html">P0004R0</a> Remove Deprecated iostreams aliases, Alisdair Meredith</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0090r0.htm">P0090R0</a> Removing result_type, etc., Stephan T. Lavavej</li>
</ul>


</body>
</html>
