[u|bi]nary_function
inheritanceSection: 22.10 [function.objects] Status: Resolved Submitter: Daniel Krügler Opened: 2009-12-14 Last modified: 2017-03-21
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 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.
[ 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 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_wrapper
synopsis as indicated: [The intent is to remove the requirement thatreference_wrapper
derives fromunary_function
orbinary_function
if 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_function
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.]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_wrapper
derives fromunary_function
if the situation requires the definition of the typedefargument_type
andresult_type
. Note that this clause does concentrate onargument_type
alone, because theresult_type
is already ruled by p. 2 via the weak result type specification. The new way of specifyingargument_type
is 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_type
as a synonym forT1
only if the typeT
is any of the following:
- a function type or a pointer to function type taking one argument of type
T1
and returningR
- a pointer to member function
R T0::f
cv (where cv represents the member function's cv-qualifiers); the typeT1
is cvT0*
- a class type
that is derived fromwith a member typestd::unary_function<T1, R>
argument_type
; the typeT1
isT::argument_type
Change 22.10.6 [refwrap]/4 as indicated: [The intent is to remove the requirement that
reference_wrapper
derives frombinary_function
if the situation requires the definition of the typedeffirst_argument_type
,second_argument_type
, andresult_type
. Note that this clause does concentrate onfirst_argument_type
andsecond_argument_type
alone, because theresult_type
is already ruled by p. 2 via the weak result type specification. The new way of specifyingfirst_argument_type
andsecond_argument_type
is 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_type
andsecond_argument_type
as a synonym forT1
andT2
, respectively, only if the typeT
is any of the following:
- a function type or a pointer to function type taking two arguments of types
T1
andT2
and returningR
- a pointer to member function
R T0::f(T2)
cv (where cv represents the member function's cv-qualifiers); the typeT1
is cvT0*
- a class type
that is derived fromwith member typesstd::binary_function<T1, T2, R>
first_argument_type
andsecond_argument_type
; the typeT1
isT::first_argument_type
and the typeT2
isT::second_argument_type
Change 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_type
andresult_type
as a synonym forcv T*
andRet
, respectively, whenpm
is a pointer to member function with cv-qualifier cv and taking no arguments, whereRet
ispm
'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_type
as a synonym forcv T*
,T1
, andRet
, respectively, whenpm
is a pointer to member function with cv-qualifier cv and taking one argument of typeT1
, whereRet
ispm
's return type.
Proposed resolution:
Addressed by paper n3198.