1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
|
In this section we concentrate on the process by which the compiler
deduces the actual types of the template type parameters. These types are
deduced when a function template is called using a process called
emi(template parameter deduction). As we've already seen, the compiler is
able to substitute a wide range of actual types for a single formal template
type parameter. Even so, not every thinkable conversion is possible. In
particular when a function has multiple parameters of the same template type
parameter, the compiler is very restrictive when determining what argument
types are actually accepted.
When the compiler deduces the actual types for template type parameters it
em(only) considers the types of the arguments that are actually
used. Neither local variables nor the function's return value is considered in
this process. This is understandable. When a function is called the compiler
is only certain about the types of the function template's arguments. At the
point of the call it definitely does not see the types of the function's local
variables. Also, the function's return value might not actually be used or may
be assigned to a variable of a subrange (or super-range) type of a deduced
template type parameter. So, in the following example, the compiler won't ever
be able to call tt(fun()), as it won't be able to deduce the actual type for
the tt(Type) template type parameter.
verb( template <typename Type>
Type fun() // can never be called as `fun()'
{
return Type{};
})
Although the compiler won't be able to handle a call to `tt(fun())', it
em(is) possible to call tt(fun()) using an
hi(type specification: explicit)i(explicit type specification). E.g.,
tt(fun<int>()) calls tt(fun), instantiated for tt(int). This is of course
em(not) the same as em(compiler) argument deduction.
In general, when a function has multiple parameters of identical template
type parameters, the actual types must be exactly the same. So, whereas
verb( void binarg(double x, double y);)
may be called using an tt(int) and a tt(double), with the tt(int) argument
silently being converted to a tt(double), a similar function template cannot
be called using an tt(int) and tt(double) argument: the compiler won't by
itself promote tt(int) to tt(double) deciding that tt(Type) should be
tt(double):
verb( template <typename Type>
void binarg(Type const &p1, Type const &p2)
{}
int main()
{
binarg(4, 4.5); // ?? won't compile: different actual types
})
What, then, are the transformations the compiler applies when deducing
the actual types of template type parameters? It performs but three types
of
hi(template: parameter type transformation)
parameter type transformations and a fourth one to function template
non-type parameters. If it cannot deduce the actual types using these
transformations, the function template will not be considered. The
transformations performed by the compiler are:
itemization(
it() em(lvalue transformations), creating an em(rvalue) from an
em(lvalue);
it() em(qualification transformations), inserting a tt(const) modifier to
a non-constant argument type;
it() em(transformation to a base class instantiated from a class template),
using a template base class when an argument of a template derived class type
was provided in the call.
it() Standard transformations for function template non-type
parameters. This isn't a template type parameter transformation, but it refers
to any remaining template non-type parameter of function templates. For these
function parameters the compiler performs any standard conversion it has
available (e.g., tt(int) to tt(size_t), tt(int) to tt(double), etc.).
)
The purpose of the various template parameter type deduction
transformations is em(not) to match function arguments to function parameters,
but rather, having matched arguments to parameters, to determine the em(actual
types) of the various template type parameters.
|