<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 1290: Don't require [u|bi]nary_function inheritance</title>
<meta property="og:title" content="Issue 1290: Don't require [u|bi]nary_function inheritance">
<meta property="og:description" content="C++ library issue. Status: Resolved">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue1290.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  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}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#Resolved">Resolved</a> status.</em></p>
<h3 id="1290"><a href="lwg-defects.html#1290">1290</a>. Don't require <code>[u|bi]nary_function</code> inheritance</h3>
<p><b>Section:</b> 22.10 <a href="https://wg21.link/function.objects">[function.objects]</a> <b>Status:</b> <a href="lwg-active.html#Resolved">Resolved</a>
 <b>Submitter:</b> Daniel Kr&uuml;gler <b>Opened:</b> 2009-12-14 <b>Last modified:</b> 2025-03-13</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View all other</b> <a href="lwg-index.html#function.objects">issues</a> in [function.objects].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#Resolved">Resolved</a> status.</p>
<p><b>Discussion:</b></p>
<p>
This issue is a follow-up of the discussion on issue <a href="lwg-defects.html#870" title="Do unordered containers not support function pointers for predicate&#47;hasher? (Status: C++11)">870</a><sup><a href="https://cplusplus.github.io/LWG/issue870" title="Latest snapshot">(i)</a></sup> during
the 2009 Santa Cruz meeting.
</p>

<p>
The class templates <code>unary_function</code> and <code>binary_function</code> are
actually very simple typedef providers,
</p>

<blockquote><pre>
namespace std {

template &lt;class Arg, class Result&gt;
struct unary_function {
 typedef Arg argument_type;
 typedef Result result_type;
};

template &lt;class Arg1, class Arg2, class Result&gt;
struct binary_function {
 typedef Arg1 first_argument_type;
 typedef Arg2 second_argument_type;
 typedef Result result_type;
};

}
</pre></blockquote>

<p>
which <i>may</i> be used as base classes (similarly to the iterator template),
but were originally <i>not</i> intended as a customization point. The SGI
documentation introduced the concept 
<a href="https://www.boost.org/sgi/stl/AdaptableUnaryFunction.html">Adaptable Unary
Function</a> as function objects "with nested typedefs that define its argument
type and result type" and a similar definition for 
<a href="https://www.boost.org/sgi/stl/AdaptableBinaryFunction.html">Adaptable Binary
Function</a> related to <code>binary_function</code>. But as of TR1 a protocol was
introduced that relies on inheritance relations based on these types. 22.10.6 <a href="https://wg21.link/refwrap">[refwrap]</a>/3 b. 3 requires that a specialization of
<code>reference_wrapper&lt;T&gt;</code> shall derive from <code>unary_function</code>,
if type <code>T</code> is "a class type that is derived from
<code>std::unary_function&lt;T1, R&gt;</code>" and a similar inheritance-based rule
for <code>binary_function</code> exists as well.
</p>

<p>
As another disadvantage it has been pointed out in the TR1 issue list, <a
href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1837.pdf">N1837</a>
(see section 10.39), that the requirements of <code>mem_fn</code> 22.10.16 <a href="https://wg21.link/func.memfn">[func.memfn]</a>/2+3 to <em>derive</em> from
<code>std::unary_function/std::binary_function</code> under circumstances, where the
provision of corresponding typedefs would be sufficient, unnecessarily prevent
implementations that take advantage of empty-base-class optimizations.
</p>

<p>
Both requirements should be relaxed in the sense that the
<code>reference_wrapper</code> should provide typedef's <code>argument_type</code>,
<code>first_argument_type</code>, and <code>second_argument_type</code> based on similar
rules as the <i>weak result type</i> rule (22.10.4 <a href="https://wg21.link/func.require">[func.require]</a>/3) does
specify the presence of <code>result_type</code> member types.
</p>

<p>
For a related issue see also <a href="lwg-defects.html#1279" title="forbid [u|bi]nary_function specialization (Status: C++11)">1279</a><sup><a href="https://cplusplus.github.io/LWG/issue1279" title="Latest snapshot">(i)</a></sup>.
</p>

<p><i>[
2010-10-24 Daniel adds:
]</i></p>


<blockquote><p>
Accepting <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3145.html">n3145</a> 
would resolve this issue as NAD editorial.
</p></blockquote>

<p><i>[
2010-11 Batavia: Solved by N3198
]</i></p>

<p>
Resolved by adopting <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3198.htm">n3198</a>.
</p>

<p>
Previous proposed resolution:
</p>
<p><i>[
The here proposed resolution is an attempt to realize the common denominator of
the reflector threads c++std-lib-26011, c++std-lib-26095, and c++std-lib-26124.
]</i></p>

<blockquote class="note">
<ol>
<li>
<p>
Change  [base]/1 as indicated: <i>[The intend is to provide an
alternative fix for issue <a href="lwg-defects.html#1279" title="forbid [u|bi]nary_function specialization (Status: C++11)">1279</a><sup><a href="https://cplusplus.github.io/LWG/issue1279" title="Latest snapshot">(i)</a></sup> and some editorial harmonization
with existing wording in the library, like 99 [iterator.basic]/1]</i>
</p>

<blockquote>
<p>
1 The following class<ins> templat</ins>es are provided to simplify the
<ins>definition of</ins> typedefs of the argument and result types <ins>for
function objects. The behavior of a program that adds specializations for any of
these templates is undefined.</ins><del>:</del>
</p>

<blockquote><pre>
namespace std {
 template &lt;class Arg, class Result&gt;
 struct unary_function {
   typedef Arg argument_type;
   typedef Result result_type;
 };
}

namespace std {
 template &lt;class Arg1, class Arg2, class Result&gt;
 struct binary_function {
   typedef Arg1 first_argument_type;
   typedef Arg2 second_argument_type;
   typedef Result result_type;
 };
}
</pre></blockquote>
</blockquote>
</li>

<li>
<p>
Change 22.10.6 <a href="https://wg21.link/refwrap">[refwrap]</a>, class template <code>reference_wrapper</code>
synopsis as indicated: <i>[The intent is to remove the requirement that
<code>reference_wrapper</code> derives from <code>unary_function</code> or
<code>binary_function</code> if the situation requires the definition of the
typedefs <code>argument_type</code>, <code>first_argument_type</code>, or
<code>second_argument_type</code>. This change is suggested, because the new way of
definition uses the same strategy as the <em>weak result type</em> specification
applied to argument types, which provides the following advantages: It creates
less potential conflicts between <code>[u|bi]nary_function</code> bases and typedefs
in a function object and it ensures that user-defined function objects which
provide typedefs but no such bases are handled as first class citizens.]</i>
</p>

<blockquote><pre>
namespace std {
 template &lt;class T&gt; class reference_wrapper
   <del>: public unary_function&lt;T1, R&gt; // <i>see below</i></del>
   <del>: public binary_function&lt;T1, T2, R&gt; // <i>see below</i></del>
 {
 public :
   // types
   typedef T type;
   typedef <i>see below</i> result_type; // not always defined
   <ins>typedef <i>see below</i> argument_type; // not always defined</ins>
   <ins>typedef <i>see below</i> first_argument_type; // not always defined</ins>
   <ins>typedef <i>see below</i> second_argument_type; // not always defined</ins>

   // construct/copy/destroy
   ...
 };
</pre></blockquote>
</li>

<li>
<p>
Change 22.10.6 <a href="https://wg21.link/refwrap">[refwrap]</a>/3 as indicated: <i>[The intent is to remove the
requirement that <code>reference_wrapper</code> derives from <code>unary_function</code>
if the situation requires the definition of the typedef <code>argument_type</code>
and <code>result_type</code>. Note that this clause does concentrate on
<code>argument_type</code> alone, because the <code>result_type</code> is already ruled
by p. 2 via the <em>weak result type</em> specification. The new way of
specifying <code>argument_type</code> is equivalent to the <em>weak result type</em>
specification]</i>
</p>

<blockquote>
<p>
3 The template instantiation <code>reference_wrapper&lt;T&gt;</code> shall <del>be
derived from <code>std::unary_function&lt;T1, R&gt;</code></del><ins>define a nested
type named <code>argument_type</code> as a synonym for <code>T1</code></ins> only if the
type <code>T</code> is any of the following:
</p>
<ul>
<li>a function type or a pointer to function type taking one argument
of type <code>T1</code><del> and returning <code>R</code></del>
</li>
<li>a pointer to member function <code>R T0::f</code> <em>cv</em> (where
<em>cv</em> represents the member function's cv-qualifiers);
the type <code>T1</code> is <em>cv</em> <code>T0*</code>
</li>
<li>a class type <del>that is derived from
<code>std::unary_function&lt;T1, R&gt;</code></del><ins>with a member type
<code>argument_type</code>;
	the type <code>T1</code> is <code>T::argument_type</code></ins>
</li>
</ul>
</blockquote>
</li>

<li>
<p>
Change 22.10.6 <a href="https://wg21.link/refwrap">[refwrap]</a>/4 as indicated: <i>[The intent is to remove the
requirement that <code>reference_wrapper</code> derives from
<code>binary_function</code> if the situation requires the definition of the typedef
<code>first_argument_type</code>, <code>second_argument_type</code>, and
<code>result_type</code>. Note that this clause does concentrate on
<code>first_argument_type</code> and <code>second_argument_type</code> alone, because
the <code>result_type</code> is already ruled by p. 2 via the <em>weak result
type</em> specification. The new way of specifying <code>first_argument_type</code>
and <code>second_argument_type</code> is equivalent to the <em>weak result type</em>
specification]</i>
</p>

<blockquote>
<p>
The template instantiation <code>reference_wrapper&lt;T&gt;</code> shall <del>be
derived from <code>std::binary_function&lt;T1, T2, R&gt;</code></del><ins>define two
nested types named <code>first_argument_type</code> and
<code>second_argument_type</code> as a synonym for <code>T1</code> and <code>T2</code>,
respectively,</ins> only if the type <code>T</code> is any of the following:
</p>
<ul>
<li>a function type or a pointer to function type taking two arguments
of types <code>T1</code> and <code>T2</code><del> and returning
<code>R</code></del>
</li>
<li>a pointer to member function <code>R T0::f(T2)</code> <em>cv</em>
(where <em>cv</em> represents the member function's cv-qualifiers);
	the type <code>T1</code> is <em>cv</em> <code>T0*</code>
</li>
<li>a class type <del>that is derived from
<code>std::binary_function&lt;T1, T2, R&gt;</code></del><ins>with member
types <code>first_argument_type</code>
	and <code>second_argument_type</code>; the type <code>T1</code> is
<code>T::first_argument_type</code> and the type <code>T2</code> is
	<code>T::second_argument_type</code></ins>
</li>
</ul>
</blockquote>
</li>

<li>
<p>
Change 22.10.16 <a href="https://wg21.link/func.memfn">[func.memfn]</a>/2+3 as indicated: <i>[The intent is to remove
the requirement that mem_fn's return type has to derive
from <code>[u|bi]nary_function</code>. The reason for suggesting the
change here is to better support empty-base-class optimization
choices as has been pointed out in 
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1837.pdf">N1837</a>]</i>
</p>

<blockquote>
<p>
2 The simple call wrapper shall <del>be derived from
<code>std::unary_function&lt;<em>cv</em> T*, <i>Ret</i>&gt;</code></del><ins>define
two nested types named <code>argument_type</code> and <code>result_type</code> as a
synonym for <code><em>cv</em> T*</code> and <code><i>Ret</i></code>, respectively,</ins>
when <code>pm</code> is a pointer to member function with cv-qualifier <em>cv</em>
and taking no arguments, where <code><i>Ret</i></code> is <code>pm</code>'s return type.
</p>
<p>
3 The simple call wrapper shall <del>be derived from
<code>std::binary_function&lt;<em>cv</em> T*, T1,
<i>Ret</i>&gt;</code></del><ins>define three nested types named
<code>first_argument_type</code>, <code>second_argument_type</code>, and
<code>result_type</code> as a synonym for <code><em>cv</em> T*</code>, <code>T1</code>, and
<code><i>Ret</i></code>, respectively,</ins> when <code>pm</code> is a pointer to member
function with cv-qualifier <em>cv</em> and taking one argument of type
<code>T1</code>, where <code><i>Ret</i></code> is <code>pm</code>'s return type.
</p>
</blockquote>
</li>

</ol>
</blockquote>

<p id="res-1290"><b>Proposed resolution:</b></p><p>
Addressed by paper <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3198.htm">n3198</a>.
</p>



</body>
</html>
