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,
|
2014-01-05 19:56:36 +01: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)
|
|
|
|
}
|
2006-09-04 10:26:34 +02:00
|
|
|
)
|
|
|
|
)
|
|
|
|
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:
|
2014-01-05 19:56:36 +01:00
|
|
|
verb(
|
|
|
|
template<typename Type>
|
|
|
|
Type sum(Type *tp, size_t n)
|
|
|
|
{
|
|
|
|
return accumulate(tp, tp + n, Type());
|
|
|
|
}
|
|
|
|
int main()
|
|
|
|
{
|
|
|
|
int x[10];
|
|
|
|
sum(x, 10);
|
|
|
|
}
|
2006-09-04 10:26:34 +02:00
|
|
|
)
|
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:
|
2014-09-23 22:09:37 +02:00
|
|
|
verbinclude(-a examples/lvalue.cc)
|
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)
|
2011-02-25 11:39:57 +01:00
|
|
|
in the process (note that tt(sqrt) is the em(address) of a function, not a
|
|
|
|
variable that is a pointer to a function, hence the lvalue
|
2011-06-08 21:22:06 +02:00
|
|
|
transformation).
|
2011-02-25 11:39:57 +01:00
|
|
|
|
|
|
|
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.
|
|
|
|
)
|
|
|
|
)
|