mirror of
https://gitlab.com/fbb-git/cppannotations
synced 2024-11-18 10:06:54 +01:00
wip
git-svn-id: https://cppannotations.svn.sourceforge.net/svnroot/cppannotations/trunk@512 f6dd340e-d3f9-0310-b409-bdd246841980
This commit is contained in:
parent
e11d7fd37f
commit
0efd6fd8d5
1 changed files with 35 additions and 32 deletions
|
@ -1,22 +1,22 @@
|
|||
Consider tt(string)'s member tt(insert). tt(String::insert) has several
|
||||
overloaded implementations. It can be used to insert text (completely or
|
||||
partially) provided in a tt(string) or in a tt(char const *) argument; to
|
||||
partially) provided by a tt(string) or by a tt(char const *) argument; to
|
||||
insert single characters a specified number of times; iterators can be used to
|
||||
specify the range of characters to be inserted; etc., etc.. All in,
|
||||
tt(string) offers five overloaded tt(insert) members.
|
||||
tt(string) offers as many as five overloaded tt(insert) members.
|
||||
|
||||
Assume the existence of a class tt(Inserter) that is used to insert
|
||||
information into all kinds of objects. Such a class could have a tt(string)
|
||||
data member into which information can be inserted. tt(Inserter)'s interface
|
||||
only partially has to copy tt(string)'s interface to realize this: only
|
||||
tt(string::insert)'s interfaces must be duplicated. These duplicating
|
||||
tt(string::insert)'s interfaces must be duplicated. The members duplicating
|
||||
interfaces often contain one statement (calling the appropriate member
|
||||
function of the object's data member) and are for this reason often
|
||||
implemented in-line. These wrapper functions merely emi(forward) their
|
||||
parameters to the appropriate member function of the object's data member.
|
||||
implemented in-line. Such em(wrapper functions) merely emi(forward) their
|
||||
parameters to the matching member functions of the object's data member.
|
||||
|
||||
Factory functions also frequently forward their parameters to the constructors
|
||||
of objects that they return.
|
||||
Another example is found in em(factory functions) that also frequently forward
|
||||
their parameters to the constructors of objects that they return.
|
||||
|
||||
Before the C++0x standard the interfaces of overloaded functions needed to
|
||||
be duplicated by the forwarding entity: tt(Inserter) needed to duplicate the
|
||||
|
@ -40,14 +40,16 @@ Perfect forwarding is easily implemented:
|
|||
em(rvalue reference parameter pack) (e.g., tt(Params && ... params));
|
||||
itht(forward)(std::forward) is used to forward the forwarding function's
|
||||
arguments to the nested function, keeping track of their types and
|
||||
number. Before using tt(forward) the tthi(utility) header file must
|
||||
have been included. The nested function is then called using this
|
||||
stanza for its arguments: tt(std::forward<Params>(params) ...).
|
||||
number. Before tt(forward) can be used the tthi(utility) header file
|
||||
must have been included.
|
||||
it() The nested function is called using this
|
||||
stanza to specify its arguments: tt(std::forward<Params>(params) ...).
|
||||
)
|
||||
|
||||
In the following example perfect forwarding is used to implement
|
||||
tt(Inserter::insert). The tt(insert) function that's actually called now
|
||||
depends on the types and number of arguments that are passed to
|
||||
In the following example perfect forwarding is used to implement em(one) member
|
||||
tt(Inserter::insert) that can be used to call any of the five overloaded
|
||||
tt(string::insert) members. The tt(insert) function that's actually called now
|
||||
simply depends on the types and number of arguments that are passed to
|
||||
tt(Inserter::insert):
|
||||
verb(
|
||||
class Inserter
|
||||
|
@ -69,7 +71,7 @@ tt(Inserter::insert):
|
|||
};
|
||||
)
|
||||
|
||||
A factory function returning a tt(Inserter) can also easily be implemented
|
||||
A factory function returning an tt(Inserter) can also easily be implemented
|
||||
using perfect forwarding. Rather than defining four overloaded factory
|
||||
functions a single one now suffices. By providing the factory function with an
|
||||
additional template type parameter specifying the class of the object to
|
||||
|
@ -99,11 +101,11 @@ operator used by variadic functions.
|
|||
|
||||
Perfect forwarding was introduced in section ref(CONTRACTIONS): a template
|
||||
function defining a tt(Type &¶m), with tt(Type) being a template type
|
||||
parameter will convert tt(Type &&) to tt(Tp &) if the function is called with
|
||||
an argument of type tt(Tp &). Otherwise it will bind tt(Type) to tt(Tp),
|
||||
parameter converts tt(Type &&) to tt(Tp &) if the function is called with
|
||||
an argument of type tt(Tp &). Otherwise it binds tt(Type) to tt(Tp),
|
||||
with tt(param) being defined as tt(Tp &¶m). As a result an em(lvalue)
|
||||
argument will bind to an lvalue-type (tt(Tp &)), while an em(rvalue) argument
|
||||
will bind to an rvalue-type (tt(Tp &&)).
|
||||
argument binds to an lvalue-type (tt(Tp &)), while an em(rvalue) argument
|
||||
binds to an rvalue-type (tt(Tp &&)).
|
||||
|
||||
The function tt(std::forward) merely passes the argument (and its type) on to
|
||||
the called function or object. Here is its simplified implementation:
|
||||
|
@ -116,17 +118,18 @@ the called function or object. Here is its simplified implementation:
|
|||
)
|
||||
Since tt(T &&) turns into an lvalue reference when tt(forward) is called
|
||||
with an lvalue (or lvalue reference) and remains an rvalue reference if
|
||||
tt(forward) is called with an rvalue reference and since tt(forward) (like
|
||||
tt(std::move)) anonymizes the variable passed as argument to tt(forward) the
|
||||
argument value is forwarded while keeping its type
|
||||
from the function's parameter to the called function's argument. This is
|
||||
called em(perfect forwarding) as the called function will only be called if
|
||||
the types of the arguments used when calling the `outer' function (e.g.,
|
||||
tt(factory)) exactly match the types of the parameters of the called function
|
||||
(e.g., tt(Class)'s constructor). Perfect forwarding therefore is a tool to
|
||||
uphold type safety.
|
||||
tt(forward) is called with an rvalue reference, and since tt(forward) (like
|
||||
tt(std::move)) anonymizes the variable passed as argument to tt(forward), the
|
||||
argument value is forwarded while passing its type from the function's
|
||||
parameter to the called function's argument.
|
||||
|
||||
A cosmetic improvement to tt(forward) forces users of tt(forward) to
|
||||
This is called em(perfect forwarding) as the nested function can only be
|
||||
called if the types of the arguments that were used when calling the `outer'
|
||||
function (e.g., tt(factory)) exactly match the types of the parameters of the
|
||||
nested function (e.g., tt(Class)'s constructor). Perfect forwarding therefore
|
||||
is a tool to realize type safety.
|
||||
|
||||
A cosmetic improvement to tt(forward) requires users of tt(forward) to
|
||||
specify the type to use rather than to have the compiler deduct the type as a
|
||||
result of the function template parameter type deduction's process. This is
|
||||
realized by a small support struct template:
|
||||
|
@ -144,12 +147,12 @@ implementation of tt(forward) thus becomes (cf. section ref(DISTINGUISH) for
|
|||
an explanation of the use of tt(typename)):
|
||||
verb(
|
||||
typedef <type T>
|
||||
T &&forward(typename identity<T>::type&& a)
|
||||
T &&forward(typename identity<T>::type &&arg)
|
||||
{
|
||||
return a;
|
||||
return arg;
|
||||
}
|
||||
)
|
||||
Now tt(forward) must explicitly state the tt(a)'s plain type, as in:
|
||||
Now tt(forward) must explicitly state tt(arg)'s type, as in:
|
||||
verb(
|
||||
std::forward<Params>(params)
|
||||
)
|
||||
|
@ -161,7 +164,7 @@ ref(CONTRACTIONS)) they can profitably be used to forward individual function
|
|||
hi(forward: parameters)
|
||||
parameters as well. Here is an example showing how an argument to a function
|
||||
can be forwarded from a template to a function that is itself passed to the
|
||||
template as a pointer to a (unspecified) function:
|
||||
template as a pointer to an (unspecified) function:
|
||||
verb(
|
||||
template<typename Fun, typename ArgType>
|
||||
void caller(Fun fun, ArgType &&arg)
|
||||
|
|
Loading…
Reference in a new issue