This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of Resolved status.
[u|bi]nary_function inheritanceSection: 22.10 [function.objects] Status: Resolved Submitter: Daniel Krügler Opened: 2009-12-14 Last modified: 2025-03-13
Priority: Not Prioritized
View all other issues in [function.objects].
View all issues with Resolved status.
Discussion:
This issue is a follow-up of the discussion on issue 870(i) during the 2009 Santa Cruz meeting.
The class templates unary_function and binary_function are
actually very simple typedef providers,
namespace std {
template <class Arg, class Result>
struct unary_function {
typedef Arg argument_type;
typedef Result result_type;
};
template <class Arg1, class Arg2, class Result>
struct binary_function {
typedef Arg1 first_argument_type;
typedef Arg2 second_argument_type;
typedef Result result_type;
};
}
which may be used as base classes (similarly to the iterator template),
but were originally not intended as a customization point. The SGI
documentation introduced the concept
Adaptable Unary
Function as function objects "with nested typedefs that define its argument
type and result type" and a similar definition for
Adaptable Binary
Function related to binary_function. But as of TR1 a protocol was
introduced that relies on inheritance relations based on these types. 22.10.6 [refwrap]/3 b. 3 requires that a specialization of
reference_wrapper<T> shall derive from unary_function,
if type T is "a class type that is derived from
std::unary_function<T1, R>" and a similar inheritance-based rule
for binary_function exists as well.
As another disadvantage it has been pointed out in the TR1 issue list, N1837
(see section 10.39), that the requirements of mem_fn 22.10.16 [func.memfn]/2+3 to derive from
std::unary_function/std::binary_function under circumstances, where the
provision of corresponding typedefs would be sufficient, unnecessarily prevent
implementations that take advantage of empty-base-class optimizations.
Both requirements should be relaxed in the sense that the
reference_wrapper should provide typedef's argument_type,
first_argument_type, and second_argument_type based on similar
rules as the weak result type rule (22.10.4 [func.require]/3) does
specify the presence of result_type member types.
For a related issue see also 1279(i).
[ 2010-10-24 Daniel adds: ]
Accepting n3145 would resolve this issue as NAD editorial.
[ 2010-11 Batavia: Solved by N3198 ]
Resolved by adopting n3198.
Previous proposed resolution:
[ 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. ]
Change [base]/1 as indicated: [The intend is to provide an alternative fix for issue 1279(i) and some editorial harmonization with existing wording in the library, like 99 [iterator.basic]/1]
1 The following class templates are provided to simplify the definition of typedefs of the argument and result types for function objects. The behavior of a program that adds specializations for any of these templates is undefined.
:namespace std { template <class Arg, class Result> struct unary_function { typedef Arg argument_type; typedef Result result_type; }; } namespace std { template <class Arg1, class Arg2, class Result> struct binary_function { typedef Arg1 first_argument_type; typedef Arg2 second_argument_type; typedef Result result_type; }; }Change 22.10.6 [refwrap], class template
reference_wrappersynopsis as indicated: [The intent is to remove the requirement thatreference_wrapperderives fromunary_functionorbinary_functionif the situation requires the definition of the typedefsargument_type,first_argument_type, orsecond_argument_type. This change is suggested, because the new way of definition uses the same strategy as the weak result type specification applied to argument types, which provides the following advantages: It creates less potential conflicts between[u|bi]nary_functionbases 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.]namespace std { template <class T> class reference_wrapper: public unary_function<T1, R> // see below: public binary_function<T1, T2, R> // see below{ public : // types typedef T type; typedef see below result_type; // not always defined typedef see below argument_type; // not always defined typedef see below first_argument_type; // not always defined typedef see below second_argument_type; // not always defined // construct/copy/destroy ... };Change 22.10.6 [refwrap]/3 as indicated: [The intent is to remove the requirement that
reference_wrapperderives fromunary_functionif the situation requires the definition of the typedefargument_typeandresult_type. Note that this clause does concentrate onargument_typealone, because theresult_typeis already ruled by p. 2 via the weak result type specification. The new way of specifyingargument_typeis equivalent to the weak result type specification]3 The template instantiation
reference_wrapper<T>shallbe derived fromdefine a nested type namedstd::unary_function<T1, R>argument_typeas a synonym forT1only if the typeTis any of the following:
- a function type or a pointer to function type taking one argument of type
T1and returningR- a pointer to member function
R T0::fcv (where cv represents the member function's cv-qualifiers); the typeT1is cvT0*- a class type
that is derived fromwith a member typestd::unary_function<T1, R>argument_type; the typeT1isT::argument_typeChange 22.10.6 [refwrap]/4 as indicated: [The intent is to remove the requirement that
reference_wrapperderives frombinary_functionif the situation requires the definition of the typedeffirst_argument_type,second_argument_type, andresult_type. Note that this clause does concentrate onfirst_argument_typeandsecond_argument_typealone, because theresult_typeis already ruled by p. 2 via the weak result type specification. The new way of specifyingfirst_argument_typeandsecond_argument_typeis equivalent to the weak result type specification]The template instantiation
reference_wrapper<T>shallbe derived fromdefine two nested types namedstd::binary_function<T1, T2, R>first_argument_typeandsecond_argument_typeas a synonym forT1andT2, respectively, only if the typeTis any of the following:
- a function type or a pointer to function type taking two arguments of types
T1andT2and returningR- a pointer to member function
R T0::f(T2)cv (where cv represents the member function's cv-qualifiers); the typeT1is cvT0*- a class type
that is derived fromwith member typesstd::binary_function<T1, T2, R>first_argument_typeandsecond_argument_type; the typeT1isT::first_argument_typeand the typeT2isT::second_argument_typeChange 22.10.16 [func.memfn]/2+3 as indicated: [The intent is to remove the requirement that mem_fn's return type has to derive from
[u|bi]nary_function. The reason for suggesting the change here is to better support empty-base-class optimization choices as has been pointed out in N1837]2 The simple call wrapper shall
be derived fromdefine two nested types namedstd::unary_function<cv T*, Ret>argument_typeandresult_typeas a synonym forcv T*andRet, respectively, whenpmis a pointer to member function with cv-qualifier cv and taking no arguments, whereRetispm's return type.3 The simple call wrapper shall
be derived fromdefine three nested types namedstd::binary_function<cv T*, T1, Ret>first_argument_type,second_argument_type, andresult_typeas a synonym forcv T*,T1, andRet, respectively, whenpmis a pointer to member function with cv-qualifier cv and taking one argument of typeT1, whereRetispm's return type.
Proposed resolution:
Addressed by paper n3198.