2006-09-04 10:26:34 +02:00
|
|
|
There are three types of emi(lvalue transformations):
|
|
|
|
itemization(
|
|
|
|
it() bf(lvalue-to-rvalue transformations.)
|
2007-05-25 15:20:15 +02:00
|
|
|
quote(An i(lvalue-to-rvalue transformation) is applied when an
|
2010-01-29 15:32:15 +01:00
|
|
|
tt(rvalue) is required, but an tt(lvalue) is provided. This happens when a
|
|
|
|
variable is used as argument to a function specifying a em(value
|
|
|
|
parameter). For example,
|
2006-09-04 10:26:34 +02:00
|
|
|
verb(
|
|
|
|
template<typename Type>
|
|
|
|
Type negate(Type value)
|
|
|
|
{
|
|
|
|
return -value;
|
|
|
|
}
|
|
|
|
int main()
|
|
|
|
{
|
|
|
|
int x = 5;
|
|
|
|
x = negate(x); // lvalue (x) to rvalue (copies x)
|
|
|
|
}
|
|
|
|
)
|
|
|
|
)
|
|
|
|
it() bf(array-to-pointer transformations.)
|
2010-01-29 15:32:15 +01:00
|
|
|
quote(An i(array-to-pointer transformation) is applied when the name
|
|
|
|
of an array is assigned to a pointer variable. This is frequently used with
|
|
|
|
functions defining pointer parameters. Such functions frequently receive
|
|
|
|
arrays as their arguments. The array's address is then assigned to the
|
|
|
|
pointer-parameter and its type is used to deduce the corresponding template
|
|
|
|
parameter's type. For example:
|
2006-09-04 10:26:34 +02:00
|
|
|
verb(
|
|
|
|
template<typename Type>
|
2006-11-01 16:54:40 +01:00
|
|
|
Type sum(Type *tp, size_t n)
|
2006-09-04 10:26:34 +02:00
|
|
|
{
|
|
|
|
return accumulate(tp, tp + n, Type());
|
|
|
|
}
|
|
|
|
int main()
|
|
|
|
{
|
|
|
|
int x[10];
|
|
|
|
sum(x, 10);
|
|
|
|
}
|
|
|
|
)
|
2010-01-29 15:32:15 +01:00
|
|
|
In this example, the location of the array tt(x) is passed to tt(sum),
|
2006-09-04 10:26:34 +02:00
|
|
|
expecting a pointer to some type. Using the array-to-pointer transformation,
|
|
|
|
tt(x)'s address is considered a pointer value which is assigned to tt(tp),
|
|
|
|
deducing that tt(Type) is tt(int) in the process.
|
|
|
|
)
|
|
|
|
it() bf(function-to-pointer transformations.)
|
2010-01-29 15:32:15 +01:00
|
|
|
quote(This transformation is most frequently used with function
|
|
|
|
templates defining a parameter which is a pointer to a function. When calling
|
|
|
|
such a function the name of a function may be specified as its argument. The
|
|
|
|
address of the function is then assigned to the pointer-parameter, deducing
|
|
|
|
the template type parameter in the process. This is called a
|
2006-09-04 10:26:34 +02:00
|
|
|
i(function-to-pointer transformation). For example:
|
|
|
|
verb(
|
|
|
|
#include <cmath>
|
|
|
|
|
|
|
|
template<typename Type>
|
|
|
|
void call(Type (*fp)(Type), Type const &value)
|
|
|
|
{
|
|
|
|
(*fp)(value);
|
|
|
|
}
|
|
|
|
int main()
|
|
|
|
{
|
|
|
|
call(&sqrt, 2.0);
|
|
|
|
}
|
|
|
|
)
|
2010-01-29 15:32:15 +01:00
|
|
|
In this example, the address of the tt(sqrt) function is passed to
|
|
|
|
tt(call), expecting a pointer to a function returning a tt(Type) and expecting
|
|
|
|
a tt(Type) for its argument. Using the function-to-pointer transformation,
|
|
|
|
tt(sqrt)'s address is assigned to tt(fp), deducing that tt(Type) is tt(double)
|
|
|
|
in the process. The argument tt(2.0) could not have been specified as tt(2) as
|
|
|
|
there is no tt(int sqrt(int)) prototype. Furthermore, the function's first
|
|
|
|
parameter specifies tt(Type (*fp)(Type)), rather than tt(Type (*fp)(Type const
|
|
|
|
&)) as might have been expected from our previous discussion about how to
|
|
|
|
specify the types of function template's parameters, preferring references
|
|
|
|
over values. However, tt(fp)'s argument tt(Type) is not a function template
|
|
|
|
parameter, but a parameter of the function tt(fp) points to. Since tt(sqrt)
|
|
|
|
has prototype tt(double sqrt(double)), rather than tt(double sqrt(double const
|
|
|
|
&)), tt(call)'s parameter tt(fp) em(must) be specified as tt(Type
|
2006-09-04 10:26:34 +02:00
|
|
|
(*fp)(Type)). It's that strict.
|
|
|
|
)
|
|
|
|
)
|