Document number: | N1673=04-0113 |
Date: | September 10, 2004 |
Project: | Programming Language C++ |
Reference: | ISO/IEC IS 14882:2003(E) |
Reply to: | Pete Becker |
Dinkumware, Ltd. | |
petebecker@acm.org | |
Peter Dimov | |
pdimov@mmltd.net |
Introduction
· Framework Overview
· Summary of Proposed Changes
· Open Issues
· Proposed Changes
Technical Report 1 introduces four templates for types whose instances
can act as function objects. These templates were written by various people
at various times and with somewhat different goals. They have much in
common, however, and their specifications can be simplified by providing
a set of shared definitions that support a uniform conceptual framework.
This paper defines such a framework and applies it to the TR1 specifications
for reference_wrapper
, function
,
mem_fn
, and bind
.
Roughly speaking, TR1 defines templates for creating function objects that, when called, forward to other function objects. That formulation is muddled, however, because the two uses of the term "function objects" mean two somewhat different things. We introduce several technical terms to provide a more precise vocabulary:
TR1 provides four different kinds of call wrappers: objects of type
reference_wrapper<T>
where T
is
a callable type; objects of type function<F>
;
objects returned by calls to the template function
mem_fn
; and objects returned by calls to the template
function bind
.
The proposed changes add the framework sketched above to TR1 and rewrite the
specifications of reference_wrapper
, function
,
mem_fn
, and bind
in terms
of that framework. Most of the changes are intended to change only the way that
the specification is expressed. A few changes, however, are changes in the
requirements. These changes are:
For easier presentation, some of the proposed changes assume particular resolutions to open TR issues, as listed below. In this paper we take no position on how these issues should be resolved.
result_type
in a call wrapper
that holds a pointer to member data.Add a new subclause, "Definitions", to the beginning of [tr.func]:
The following definitions shall apply to this clause:
A call signature is the name of a return type followed by a parenthesized comma-separated list of zero or more argument types.
A call wrapper is an object of a call wrapper type.
A call wrapper type is a type that holds a callable object and supports a call operation that forwards to that object.
A callable object is an object of a callable type.
A callable type is a pointer to function, a pointer to member function, a pointer to member data, or a class type whose objects can appear immediately to the left of a function call operator.
A target object is the callable object held by a call wrapper object.
Add a new subclause, "Requirements", after [tr.func.syn]:
Define INVOKE(f, t1, t2, ..., tN) as follows:
(t1.*f)(t2, ..., tN)
whenf
is a pointer to a member function of a classT
andt1
is an object of typeT
or a reference to an object of typeT
or a reference to an object of a type derived fromT
;((*t1).*f)(t2, ..., tN)
when f is a pointer to a member function of a classT
andt1
is not one of the types described in the previous item;t1.*f
whenf
is a pointer to member data of a classT
andt1
is an object of typeT
or a reference to an object of typeT
or a reference to an object of a type derived fromT
;(*t1).*f
when f is a pointer to member data of a classT
andt1
is not one of the types described in the previous item;f(t1, t2, ..., tN)
in all other cases.
Define INVOKE(f, t1, t2, ..., tN, R) as INVOKE(f, t1, t2, ..., tN)
implicitly converted to R
.
If a call wrapper has a weak result type the type of its member typeresult_type
is based on the typeT
of the wrapper's target object:
- if
T
is a pointer to function,result_type
shall be a synonym for the return type ofT
;- if
T
is a pointer to member function,result_type
shall be a synonym for the return type ofT
;- if
T
is a pointer to member data,result_type
shall be a synonym for the declared type of the data member;3- if
T
is a class type with a member typeresult_type
, thenresult_type
shall be a synonym forT::result_type
;- otherwise
result_type
shall not be defined.
Every call wrapper shall be CopyConstructible. A simple call wrapper is a call wrapper that is Assignable and whose copy constructor and assignment operator do not throw exceptions. A forwarding call wrapper is a call wrapper that can be called with an argument listt1, t2, ..., tN
where eachti
is an lvalue. The effect of calling a forwarding call wrapper with one or more arguments that are rvalues is implementation defined. [Note: in a typical implementation forwarding call wrappers have overloaded function call operators of the formtemplate<class T1, class T2, ..., class TN> R operator()(T1& t1, T2& t2, ..., TN& tN) cv-qual;-- end note]
reference_wrapper
In [tr.util.refwrp.refwrp], remove paragraph 2 and its three bullet items and replace them with:
reference_wrapper
has a weak result type.
Remove both paragraphs of [tr.util.refwrp.invoke] and replace them with:
Returns: INVOKE(get(), a1, a2, ..., aN)
function
Remove paragraphs 1, 2, and 3 from [tr.func.wrap.func].
After the template definition in [tr.func.wrap.func] add the following:
The function
class template provides polymorphic wrappers that
generalize the notion of a function pointer. Wrappers can store, copy, and call
arbitrary callable objects, given a
call signature, allowing functions to be first-class
objects.
A function objectf
of typeF
is Callable for argument typesT1, T2, ..., TN
and a return typeR
, if, given lvaluest1, t2, ..., tN
of typesT1, T2, ..., TN
, respectively,INVOKE(f, t1, t2, ..., tN)
is well-formed and, ifR
is notvoid
, convertible toR
.
Thefunction
class template is a call wrapper whose call signature isR(T1, T2, ..., TN)
.
Remove paragraphs 1 and 2 of [tr.func.wrap.func.inv] and replace them with:
Effects:INVOKE(f, t1, t2, ..., tN, R)
, wheref
is the target object of*this
.
Returns: nothing, ifR
isvoid
, otherwise the return value ofINVOKE(f, t1, t2, ..., tN, R)
.
mem_fn
Replace [tr.func.memfn] with:
template<class R, class T> unspecified mem_fn(R T::*pm);
Returns: a simple call wrapperf
such that the expressionf(t, a2, ..., aN)
is equivalent toINVOKE(pm, t, a2, ..., aN)
.f
shall have a nested typeresult_type
that is a synonym for the return type ofpm
whenpm
is a pointer to member function, or a synonym forR
or forR const&
otherwise3.
Throws: nothing.
Notes: implementations may implement mem_fn
as a set of
overloaded function templates.
bind
Replace [tr.func.bind.bind] with:
template<class F, class T1, class T2, ...., class TN> unspecified bind(F f, T1 t1, T2 t2, ..., TN tN);
Requires:
F
andTi
shall beCopyConstructible
.INVOKE(f, w1, w2, ..., wN)
shall be a valid expression for some valuesw1, w2, ..., wN
.Returns: A forwarding call wrapper
g
with a weak result type. The effect ofg(u1, u2, ..., uM)
shall beINVOKE(f, v1, v2, ..., vN, result_of<F cv (V1, V2, ..., VN)>::type)
, wherecv
are the cv-qualifiers ofg
and the values and types of the bound argumentsv1, v2, ..., vN
are determined as specified below.
template<class R, class F, class T1, class T2, ...., class TN> unspecified bind(F f, T1 t1, T2 t2, ..., TN tN);
Requires:
F
andTi
shall beCopyConstructible
.INVOKE(f, w1, w2, ..., wN)
shall be a valid expression for some valuesw1, w2, ..., wN
.Returns: A forwarding call wrapper
g
with a nested typeresult_type
defined as a synonym forR
. The effect ofg(u1, u2, ..., uM)
shall beINVOKE(f, v1, v2, ..., vN, R)
, where the values and types of the bound argumentsv1, v2, ..., vN
are determined as specified below.
The values of the bound arguments
v1, v2, ..., vN
and their corresponding typesV1, V2, ..., VN
depend on the type of the corresponding argumentti
of typeTi
in the call tobind
and the cv-qualifiers cv of the call wrapperg
as follows:
- if
ti
is of typereference_wrapper<T>
the argument isti.get()
and its typeVi
isT&
;- if the value of
std::tr1::is_bind_expression<Ti>::value
istrue
the argument isti(u1, u2, ..., uM)
and its typeVi
isresult_of<Ti cv (U1&, U2&, ..., UM&)>::type
;- if the value
j
ofstd::tr1::is_placeholder<Ti>::value
is not zero the argument isuj
and its typeVi
isUj&
;- otherwise the value is
ti
and its typeVi
isTi cv &
.
Change the title of [tr.limits] to:
Annex A (informative) Implementation quantities
Change the text of [tr.limits] to the following:
Nmax
, the maximum number of arguments that can be forwarded by the call wrappers defined in [tr.util.refwrap], [tr.func.memfn], [tr.func.bin], [tr.func.wrap], and the maximum number of argument types that can be passed in the argument toresult_of
([tr.func.ret]), is implementation defined. The value ofNmax
should be at least 10.
The number of distinct placeholders is implementation defined. The number should be at least 10.
The maximum number of elements in one tuple
type (clause [tr.tuple])
is implementation defined. The value should be at least 10.
1. A pointer to member data cannot, of course, be "called" in the usual sense.
2. Such a type often has a member operator()
,
but in some cases it can omit that member and provide a conversion to a
pointer to function.
3. This requirement should be changed to reflect the resolution of issue 10.24. (This footnote is not intended to be part of TR1)
Portions of this document are derived from work copyright © 2004 by Dinkumware, Ltd. All such material is made available for standardization purposes only, and its inclusion does not waive the rights of Dinkumware, Ltd. under applicable copyright laws.