<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 870: Do unordered containers not support function pointers for predicate&#47;hasher?</title>
<meta property="og:title" content="Issue 870: Do unordered containers not support function pointers for predicate&#47;hasher?">
<meta property="og:description" content="C++ library issue. Status: C++11">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue870.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#C++11">C++11</a> status.</em></p>
<h3 id="870"><a href="lwg-defects.html#870">870</a>. Do unordered containers not support function pointers for predicate&#47;hasher?</h3>
<p><b>Section:</b> 23.2.8 <a href="https://wg21.link/unord.req">[unord.req]</a> <b>Status:</b> <a href="lwg-active.html#C++11">C++11</a>
 <b>Submitter:</b> Daniel Kr&uuml;gler <b>Opened:</b> 2008-08-17 <b>Last modified:</b> 2016-01-28</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View other</b> <a href="lwg-index-open.html#unord.req">active issues</a> in [unord.req].</p>
<p><b>View all other</b> <a href="lwg-index.html#unord.req">issues</a> in [unord.req].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#C++11">C++11</a> status.</p>
<p><b>Discussion:</b></p>
<p>
Good ol' associative containers allow both function pointers and
function objects as feasible comparators, as described in 
23.2.7 <a href="https://wg21.link/associative.reqmts">[associative.reqmts]</a>&#47;2:
</p>

<blockquote><p>
Each associative container is parameterized on <code>Key</code> and an ordering
relation <code>Compare</code> that induces a strict weak ordering (25.3) on 
elements of Key. [..]. The object of type <code>Compare</code> is called the 
comparison object of a container. This comparison object may be a pointer to
function or an object of a type with an appropriate function call operator.[..]
</p></blockquote>

<p>
The corresponding wording for unordered containers is not so clear,
but I read it to disallow function pointers for the hasher and I miss 
a clear statement for the equality predicate, see
23.2.8 <a href="https://wg21.link/unord.req">[unord.req]</a>&#47;3+4+5:
</p>

<blockquote>
<p>
Each unordered associative container is parameterized by <code>Key</code>, by a
function object <code>Hash</code> that
acts as a hash function for values of type <code>Key</code>, and by a binary
predicate <code>Pred</code> that induces an
equivalence relation on values of type <code>Key</code>.[..]
</p>
<p>
A hash function is a function object that takes a single argument of
type <code>Key</code> and returns a value of type <code>std::size_t</code>.
</p>
<p>
Two values <code>k1</code> and <code>k2</code> of type <code>Key</code> are considered 
equal if the container's equality function object returns <code>true</code> 
when passed those values.[..]
</p>
</blockquote>

<p>
and table 97 says in the column "assertion...post-condition" for the
expression <code>X::hasher</code>:
</p>

<blockquote><p>
<code>Hash</code> shall be a unary function object type such that the expression
<code>hf(k)</code> has type <code>std::size_t</code>.
</p></blockquote>

<p>
Note that 22.10 <a href="https://wg21.link/function.objects">[function.objects]</a>&#47;1 defines as "Function objects are
objects with an <code>operator()</code> defined.[..]"
</p>
<p>
Does this restriction exist by design or is it an oversight? If an
oversight, I suggest that to apply
the following
</p>

<p><i>[
2009-07-28 Reopened by Alisdair.  No longer solved by concepts.
]</i></p>


<p><i>[
2009-10 Santa Cruz:
]</i></p>


<blockquote><p>
Ask Daniel to provide proposed wording that: makes it explicit that
function pointers are function objects at the beginning of 
22.10 <a href="https://wg21.link/function.objects">[function.objects]</a>; fixes the "requirements" for typedefs in
22.10.6 <a href="https://wg21.link/refwrap">[refwrap]</a> to instead state that the function objects
defined in that clause have these typedefs, but not that these typedefs
are requirements on function objects; remove the wording that explicitly
calls out that associative container comparators may be function
pointers.
</p></blockquote>

<p><i>[
2009-12-19 Daniel updates wording and rationale.
]</i></p>


<p><i>[
2010-02-11 Moved to Tentatively Ready after 5 positive votes on c++std-lib.
]</i></p>




<p><b>Rationale:</b></p>

<p>
The below provided wording also affects some part of the library which is
involved with <em>callable types</em> (22.10.3 <a href="https://wg21.link/func.def">[func.def]</a>&#47;3). Reason for
this is that <em>callable objects</em> do have a lot in common with <em>function
objects</em>. A simple formula seems to be:
</p>

<blockquote><p>
callable objects = function objects + pointers to member
</p></blockquote>

<p>
The latter group is excluded from function objects because of the
expression-based usage of <em>function objects</em> in the algorithm clause,
which is incompatible with the notation to dereference pointers to member
without a concept map available in the language.
</p>

<p>
This analysis showed some currently existing normative definition differences
between the above subset of callable objects and function objects which seem to
be unintended: Backed by the Santa Cruz outcome function objects should include
both function pointers and "object[s] with an operator() defined". This clearly
excludes class types with a conversion function to a function pointer or all
similar conversion function situations described in 12.2 <a href="https://wg21.link/over.match">[over.match]</a>&#47;2
b. 2. In contrast to this, the wording for callable types seems to be less
constrained (22.10.3 <a href="https://wg21.link/func.def">[func.def]</a>/3):
</p>

<blockquote><p>
A callable type is a [..] class type whose objects can appear immediately to the
left of a function call operator.
</p></blockquote>

<p>
The rationale given in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1673.html#fn2">N1673</a>
and a recent private communication with Peter Dimov revealed that the intention
of this wording was to cover the above mentioned class types with conversion
functions as well. To me the current wording of callable types can be read
either way and I suggest to make the intention more explicit by replacing
</p>

<blockquote><p>
[..] class type whose objects can appear immediately to the left of a function
call operator
</p></blockquote>
<p>
by
</p>
<blockquote><p>
[..] class type whose objects can appear as the leftmost subexpression of a
function call expression 7.6.1.3 <a href="https://wg21.link/expr.call">[expr.call]</a>.
</p></blockquote>

<p>
and to use the same definition for the class type part of <em>function
objects</em>, because there is no reason to exclude class types with a
conversion function to e.g. pointer to function from being used in algorithms.
</p>

<p>
Now this last term "function objects" itself brings us to a third unsatisfactory
state: The term is used both for objects (e.g. "Function objects are
objects[..]" in 22.10 <a href="https://wg21.link/function.objects">[function.objects]</a>&#47;1) and for types (e.g. "Each
unordered associative container is parameterized [..] by a function object Hash
that acts as a hash function [..]" in 23.2.8 <a href="https://wg21.link/unord.req">[unord.req]</a>&#47;3). This
impreciseness should be fixed and I suggest to introduce the term <em>function
object type</em> as the counter part to <em>callable type</em>. This word seems
to be a quite natural choice, because the library already uses it here and there
(e.g. "Hash shall be a unary function object type such that the expression
<code>hf(k)</code> has type <code>std::size_t</code>." in Table 98, "<code>X::hasher</code>"
or "Requires: <code>T</code> shall be a function object type [..]" in 
22.10.17.3.6 <a href="https://wg21.link/func.wrap.func.targ">[func.wrap.func.targ]</a>&#47;3).
</p>

<p>
Finally I would like to add that part of the issue 870 discussion related to the
requirements for typedefs in 22.10.6 <a href="https://wg21.link/refwrap">[refwrap]</a> during the Santa Cruz
meeting is now handled by the new issue <a href="lwg-defects.html#1290" title="Don't require [u|bi]nary_function inheritance (Status: Resolved)">1290</a><sup><a href="https://cplusplus.github.io/LWG/issue1290" title="Latest snapshot">(i)</a></sup>.
</p>

<p>
Obsolete rationale:
</p>

<blockquote>
<p><i>[
San Francisco:
]</i></p>


<blockquote><p>
This is fixed by
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2776.pdf">N2776</a>.
</p></blockquote>

</blockquote>



<p id="res-870"><b>Proposed resolution:</b></p>

<ol>

<li>
<p>
Change 22.10 <a href="https://wg21.link/function.objects">[function.objects]</a>&#47;1 as indicated:
</p>

<blockquote>
<p>
1 <del>Function objects are objects with an <code>operator()</code>
defined.</del> <ins>An object type (6.9 <a href="https://wg21.link/basic.types">[basic.types]</a>) that can be the
type of the <em>postfix-expression</em> in a function call (7.6.1.3 <a href="https://wg21.link/expr.call">[expr.call]</a>, 
12.2.2.2 <a href="https://wg21.link/over.match.call">[over.match.call]</a>) is called a <em>function
object type</em><sup>*</sup>. A <em>function object</em> is an object of a
<em>function object type</em>.</ins> In the places where one would expect to
pass a pointer to a function to an algorithmic template (Clause 26 <a href="https://wg21.link/algorithms">[algorithms]</a>), 
the interface is specified to accept <del>an object with
an <code>operator()</code> defined</del><ins>a function object</ins>. This not only
makes algorithmic templates work with pointers to functions, but also enables
them to work with arbitrary function objects.
</p>
<blockquote><p><ins>
* Such a type is either a function pointer or a class type which often has a
member <code>operator()</code>, but in some cases it can omit that member and
provide a conversion to a pointer to function.
</ins></p></blockquote>
</blockquote>
</li>

<li>
<p>
Change 22.10.3 <a href="https://wg21.link/func.def">[func.def]</a>&#47;3 as indicated: <i>[The intent is to make the
commonality of callable types and function object
types more explicit and to get rid of wording redundancies]</i>
</p>

<blockquote><p>
3 A <i>callable type</i> is <del>a pointer to function,</del> a pointer to
member <del>function, a pointer to member data,</del> or a <del>class type whose
objects can appear immediately to the left of a function call operator</del>
<ins><em>function object type</em> (22.10 <a href="https://wg21.link/function.objects">[function.objects]</a>)</ins>.
</p></blockquote>
</li>

<li>
<p>
Change  [bind]&#47;1 as indicated:
</p>

<blockquote><p>
1 The function template <code>bind</code> returns an object that binds a
<del>function</del> <ins>callable</ins> object passed as an argument to
additional arguments.
</p></blockquote>
</li>

<li>
<p>
Change 22.10.15 <a href="https://wg21.link/func.bind">[func.bind]</a>&#47;1 as indicated:
</p>

<blockquote><p>
1 This subclause describes a uniform mechanism for binding arguments of
<del>function</del> <ins>callable</ins> objects.
</p></blockquote>
</li>

<li>
<p>
Change 22.10.17 <a href="https://wg21.link/func.wrap">[func.wrap]</a>&#47;1 as indicated:
</p>

<blockquote><p>
1 This subclause describes a polymorphic wrapper class that encapsulates
arbitrary <del>function</del> <ins>callable</ins> objects.
</p></blockquote>
</li>

<li>
<p>
Change 22.10.17.3 <a href="https://wg21.link/func.wrap.func">[func.wrap.func]</a>&#47;2 as indicated <i>[The reason for this
change is that 22.10.17.3 <a href="https://wg21.link/func.wrap.func">[func.wrap.func]</a>&#47;1 clearly says that all callable
types may be wrapped by <code>std::function</code> and current implementations
indeed do provide support for pointer to members as well. One further suggested
improvement is to set the below definition of Callable in italics]</i>:
</p>

<blockquote><p>
2 A <del>function</del><ins>callable</ins> object <code>f</code> of type <code>F</code>
is <del>Callable</del> <ins><em>Callable</em></ins> for argument types
<del><code>T1, T2, ..., TN</code> in</del> <code>ArgTypes</code> and <del>a</del> return
type <code>R</code><del>,</del> if<del>, given lvalues <code>t1, t2, ..., tN</code> of
types <code>T1, T2, ..., TN</code>, respectively,</del> <ins>the expression</ins>
<code><i>INVOKE</i>(f, <ins>declval&lt;ArgTypes&gt;()..., R</ins><del>t1, t2, ...,
tN</del>)</code><ins>, considered as an unevaluated operand (7 <a href="https://wg21.link/expr">[expr]</a>),</ins> 
is well formed (20.7.2)<del> and, if <code>R</code> is not <code>void</code>, convertible 
to <code>R</code></del>.
</p></blockquote>
</li>



<li>
<p>
Change 22.10.17.3.2 <a href="https://wg21.link/func.wrap.func.con">[func.wrap.func.con]</a>&#47;7 as indicated:
</p>

<blockquote><pre>
function(const function&amp; f);
template &lt;class A&gt; function(allocator_arg_t, const A&amp; a, const function&amp; f);
</pre>
<blockquote>
<p>...</p>
<p>
7 <i>Throws:</i> shall not throw exceptions if <code>f</code>'s target is a function
pointer or a <del>function</del> <ins>callable</ins> object passed via
<code>reference_wrapper</code>. Otherwise, may throw <code>bad_alloc</code> or any
exception thrown by the copy constructor of the stored <del>function</del>
<ins>callable</ins> object. [<i>Note:</i> Implementations are encouraged to
avoid the use of dynamically allocated memory for small <del>function</del>
<ins>callable</ins> objects, e.g., where <code>f</code>'s target is an object
holding only a pointer or reference to an object and a member function pointer.
&mdash; <i>end note</i>]
</p>
</blockquote>
</blockquote>
</li>

<li>
<p>
Change 22.10.17.3.2 <a href="https://wg21.link/func.wrap.func.con">[func.wrap.func.con]</a>&#47;11 as indicated:
</p>

<blockquote><pre>
template&lt;class F&gt; function(F f);
template &lt;class F, class A&gt; function(allocator_arg_t, const A&amp; a, F f);
</pre>
<blockquote>
<p>...</p>
<p>
11 [..] [<i>Note:</i> implementations are encouraged to avoid the use of dynamically
allocated memory for small <del>function</del> <ins>callable</ins> objects, for
example, where <code>f</code>'s target is an object holding only a pointer or
reference to an object and a member function pointer. &mdash; <i>end note</i>]
</p>
</blockquote>
</blockquote>
</li>

<li>
<p>
Change 22.10.17.3.5 <a href="https://wg21.link/func.wrap.func.inv">[func.wrap.func.inv]</a>&#47;3 as indicated:
</p>

<blockquote><pre>
R operator()(ArgTypes... args) const
</pre>
<blockquote>
<p>...</p>
<p>
3 <i>Throws:</i> <code>bad_function_call</code> if <code>!*this</code>; otherwise, any
exception thrown by the wrapped <del>function</del> <ins>callable</ins> object.
</p>
</blockquote>
</blockquote>
</li>

<li>
<p>
Change 22.10.17.3.6 <a href="https://wg21.link/func.wrap.func.targ">[func.wrap.func.targ]</a>&#47;3 as indicated:
</p>

<blockquote><pre>
template&lt;typename T&gt;       T* target();
template&lt;typename T&gt; const T* target() const;
</pre>
<blockquote>
<p>...</p>
<p>
3 <i>Requires:</i> <code>T</code> shall be a <del>function object</del> type that is
Callable (22.10.17.3 <a href="https://wg21.link/func.wrap.func">[func.wrap.func]</a>) for parameter types <code>ArgTypes</code>
and return type <code>R</code>.
</p>
</blockquote>
</blockquote>
</li>

<li>
<p>
Change 23.2.7 <a href="https://wg21.link/associative.reqmts">[associative.reqmts]</a>&#47;2 as indicated: <i>[The suggested
removal seems harmless, because 26.8 <a href="https://wg21.link/alg.sorting">[alg.sorting]</a>1 already clarifies
that <code>Compare</code> is a function object type. Nevertheless it is recommended,
because the explicit naming of "pointer to function" is misleading]</i>
</p>

<blockquote><p>
2 Each associative container is parameterized on <code>Key</code> and an ordering
relation <code>Compare</code> that induces a strict weak ordering (26.8 <a href="https://wg21.link/alg.sorting">[alg.sorting]</a>) 
on elements of <code>Key</code>. In addition, <code>map</code> and <code>multimap</code> 
associate an arbitrary type <code>T</code> with the <code>Key</code>. The object of type 
<code>Compare</code> is called the comparison object of a container. <del>This 
comparison object may be a pointer to function or an object of a type with an 
appropriate function call operator.</del>
</p></blockquote>
</li>

<li>
<p>
Change 23.2.8 <a href="https://wg21.link/unord.req">[unord.req]</a>&#47;3 as indicated:
</p>

<blockquote><p>
3 Each unordered associative container is parameterized by <code>Key</code>, by a
function object <ins>type</ins> <code>Hash</code> that acts as a hash function for
values of type <code>Key</code>, and by a binary predicate <code>Pred</code> that
induces an equivalence relation on values of type Key. [..]
</p></blockquote>
</li>

<li>
<p>
Change 26.1 <a href="https://wg21.link/algorithms.general">[algorithms.general]</a>&#47;7 as indicated: <i>[The intent is to
bring this part in sync with 22.10 <a href="https://wg21.link/function.objects">[function.objects]</a>]</i>
</p>

<blockquote><p>
7 The <code>Predicate</code> parameter is used whenever an algorithm expects a
function object <ins>(22.10 <a href="https://wg21.link/function.objects">[function.objects]</a>)</ins> that when applied
to the result of dereferencing the corresponding iterator returns a value
testable as <code>true</code>. In other words, if an algorithm takes <code>Predicate
pred</code> as its argument and <code>first</code> as its iterator argument, it should
work correctly in the construct <code>if (pred(*first)){...}</code>. The function
object <code>pred</code> shall not apply any nonconstant function through the
dereferenced iterator. <del>This function object may be a pointer to function,
or an object of a type with an appropriate function call operator.</del>
</p></blockquote>
</li>

<li>
<p>
Change 20.3.1.3 <a href="https://wg21.link/unique.ptr.single">[unique.ptr.single]</a>&#47;1 as indicated:
</p>

<blockquote><p>
1 The default type for the template parameter <code>D</code> is
<code>default_delete</code>. A client-supplied template argument <code>D</code> shall be
a function <del>pointer or functor</del> <ins>object type</ins> for which, given
a value <code>d</code> of type <code>D</code> and a pointer <code>ptr</code> of type
<code>T*</code>, the expression <code>d(ptr)</code> is valid and has the effect of
deallocating the pointer as appropriate for that deleter. <code>D</code> may also be
an lvalue-reference to a deleter.
</p></blockquote>
</li>

</ol>








</body>
</html>
