| 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)whenfis a pointer to a member function of a classTandt1is an object of typeTor a reference to an object of typeTor 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 classTandt1is not one of the types described in the previous item;t1.*fwhenfis a pointer to member data of a classTandt1is an object of typeTor a reference to an object of typeTor a reference to an object of a type derived fromT;(*t1).*fwhen f is a pointer to member data of a classTandt1is 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_typeis based on the typeTof the wrapper's target object:
- if
Tis a pointer to function,result_typeshall be a synonym for the return type ofT;- if
Tis a pointer to member function,result_typeshall be a synonym for the return type ofT;- if
Tis a pointer to member data,result_typeshall be a synonym for the declared type of the data member;3- if
Tis a class type with a member typeresult_type, thenresult_typeshall be a synonym forT::result_type;- otherwise
result_typeshall 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, ..., tNwhere eachtiis 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_wrapperIn [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)
functionRemove 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 objectfof typeFis Callable for argument typesT1, T2, ..., TNand a return typeR, if, given lvaluest1, t2, ..., tNof typesT1, T2, ..., TN, respectively,INVOKE(f, t1, t2, ..., tN)is well-formed and, ifRis notvoid, convertible toR.
Thefunctionclass 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), wherefis the target object of*this.
Returns: nothing, ifRisvoid, otherwise the return value ofINVOKE(f, t1, t2, ..., tN, R).
mem_fnReplace [tr.func.memfn] with:
template<class R, class T>
unspecified mem_fn(R T::*pm);
Returns: a simple call wrapperfsuch that the expressionf(t, a2, ..., aN)is equivalent toINVOKE(pm, t, a2, ..., aN).fshall have a nested typeresult_typethat is a synonym for the return type ofpmwhenpmis a pointer to member function, or a synonym forRor forR const&otherwise3.
Throws: nothing.
Notes: implementations may implement mem_fn as a set of
overloaded function templates.
bindReplace [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:
FandTishall beCopyConstructible.INVOKE(f, w1, w2, ..., wN)shall be a valid expression for some valuesw1, w2, ..., wN.Returns: A forwarding call wrapper
gwith a weak result type. The effect ofg(u1, u2, ..., uM)shall beINVOKE(f, v1, v2, ..., vN, result_of<F cv (V1, V2, ..., VN)>::type), wherecvare the cv-qualifiers ofgand the values and types of the bound argumentsv1, v2, ..., vNare 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:
FandTishall beCopyConstructible.INVOKE(f, w1, w2, ..., wN)shall be a valid expression for some valuesw1, w2, ..., wN.Returns: A forwarding call wrapper
gwith a nested typeresult_typedefined 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, ..., vNare determined as specified below.
The values of the bound arguments
v1, v2, ..., vNand their corresponding typesV1, V2, ..., VNdepend on the type of the corresponding argumenttiof typeTiin the call tobindand the cv-qualifiers cv of the call wrappergas follows:
- if
tiis of typereference_wrapper<T>the argument isti.get()and its typeViisT&;- if the value of
std::tr1::is_bind_expression<Ti>::valueistruethe argument isti(u1, u2, ..., uM)and its typeViisresult_of<Ti cv (U1&, U2&, ..., UM&)>::type;- if the value
jofstd::tr1::is_placeholder<Ti>::valueis not zero the argument isujand its typeViisUj&;- otherwise the value is
tiand its typeViisTi 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 ofNmaxshould 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.