<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">P0005R0</td>
</tr>
<tr>
  <td align="left">Date:</td>
  <td align="left">2015-09-28</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>
</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="#1.0">Introduction</a></li>
<li><a href="#2.0">Recommended for Immediate Adoption</a></li>
<li><a href="#3.0">Remove the Classic <tt>not1</tt> and <tt>not2</tt> negators</a></li>
<li><a href="#4.0">Future Extensions</a></li>
<li><a href="#5.0">Established Experience</a></li>
<li><a href="#6.0">Proposed Wording</a></li>
<li><a href="#7.0">Acknowledgements</a></li>
<li><a href="#8.0">References</a></li>
</ul>


<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.
</p>


<h2><a name="2.0">Recommenation for Immediate Adoption</a></h2>
<p>
The function template <tt>not_fn</tt> is first proposed 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 reprecate, and ultimately remove, this final legacy.
</p>
<p>
Note that it is desirable to finally remove the legacy adaptable function protocol
as it makes implementing sevaral library types considerably more awkward with
conditionally defined member typedefs, such as <tt>std::function</tt> wrapping a
function type with exactly one or two parameters, or similarly for
<tt>std::reference_wrapper</tt> for function references of exactly one or two
arguments.  Meanwhile, the adaptable protocol is not supported for newer language
features, such as lambda expressions, and actually cannot be supported for some
features such as polymorphic lambda expressions.
</p>


<h2><a name="3.0">Remove the Classic <tt>not1</tt> and <tt>not2</tt> negators</a></h2>
<p>
Traditionally we would start a long deprecatation 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 targetted 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>
<p>
One the last of the classic binders are removed, then all of the support machinery
created only for them, that no longer functions as well as designed with the
addition of lambda expressios and other recent language and library features, should
also be removed.  That means removing all of the <tt>argument_type</tt>,
<tt>first_arguement_type</tt>, and <tt>second_argument_type</tt> typedefs in the
standard library, but <em>retaining</em> the <tt>result_type</tt> typedefs which
are also part of the <i>INVOKE</i> protocol.
</p>


<h2><a name="4.0">Future Extensions</a></h2>
<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 tricker 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 unsepcified 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>
<p>
Amend the <tt>&lt;function&gt;</tt> header sysnopsis 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 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>
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;
    typedef <i>see below</i> result_type;              <i>// not always defined</i>
    <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>
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>.
</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>
Replace subclause <b>20.9.9 [negators]</b> with a new subclause <b>20.9.9 [func.notfn]</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 FD constructed from <tt>std::forward&lt;F&gt;(f)</tt>,</li></ins>
<li><ins><tt>fn</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>fn</tt> such that the expression <tt>fn(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>
Strike the un-nessary typedefs from the unspecified return-type of <tt>mem_fn</tt> (note that the first
bullet continues to provide <tt>result_type</tt> when the second and third bullets are removed):
</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) fn 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). <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.
</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 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>
Ammend 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><ins>
(1.3) — provide a nested type, <tt>result_type</tt>, which shall be synonyms for <tt>size_t</tt>,
</ins></p>
<p>
(1.4) — satisfy the requirement that if k1 == k2 is true, h(k1) == h(k2) is also true, where h is an object of type hash<Key> and k1 and k2 are objects of type Key;
</p>
<p>
(1.5) — satisfy the requirement that the expression h(k), where h is an object of type hash<Key> and k is an object of type Key, shall not throw an exception unless hash<Key> is a user-defined specialization that depends on at least one user-defined type.
</p>
</blockquote>


<p>
Strike the <tt>argument_type</tt>, <tt>first_argument_type</tt>, and <tt>second_argument_type</tt>
typedefs from all standard library classes, including (but not limited to):
</p>
<ul>
  <li>20.8.2.4 <tt>owner_lessx</tt></li>
  <li>20.9.5 <tt>plus</tt></li>
  <li>20.9.5 <tt>minus</tt></li>
  <li>20.9.5 <tt>multiplies</tt></li>
  <li>20.9.5 <tt>divides</tt></li>
  <li>20.9.5 <tt>modulus</tt></li>
  <li>20.9.5 <tt>negate</tt></li>
  <li>20.9.6 <tt>equal_to</tt></li>
  <li>20.9.6 <tt>not_equal_to</tt></li>
  <li>20.9.6 <tt>greater</tt></li>
  <li>20.9.6 <tt>less</tt></li>
  <li>20.9.6 <tt>greater_equal</tt></li>
  <li>20.9.6 <tt>less_equal</tt></li>
  <li>20.9.7 <tt>logical_and</tt></li>
  <li>20.9.7 <tt>logical_or</tt></li>
  <li>20.9.7 <tt>logical_not</tt></li>
  <li>20.9.8 <tt>bit_and</tt></li>
  <li>20.9.8 <tt>bit_or</tt></li>
  <li>20.9.8 <tt>bit_xor</tt></li>
  <li>20.9.8 <tt>bit_not</tt></li>
  <li>23.4.4.1 <tt>map::compare</tt></li>
  <li>23.4.5.1 <tt>multimap::compare</tt></li>
</ul>


<p>
Optionally excise class 3 from the Library Fundamentals 2 TS, as it is no longer required (section numbering
per <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4481.html">n4481</a>).
</p>


<h2><a name="7.0">Acknowledgements</a></h2>
<p>
Thanks to Tomasz Kamiński for writing up and proposing this feature for the Library Fudamentals TS,
this is essentially his work that I am trying to promote!
</p>


<h2><a name="8.0">References</h2>
<ul>
  <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</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></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</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0004r0.html">P0004R0</a> Remove Deprecated iostreams aliases</li>
</ul>


</body>
</html>
