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
|
Consider the following definition of the tt(add()) template function:
verb(
template <typename Container, typename Type>
Type add(Container const &container, Type init)
{
return std::accumulate(container.begin(), container.end(), init);
}
)
In this template definition, tt(std::accumulate()) is called, using
tt(container)'s tt(begin()) and tt(end()) members.
The calls tt(container.begin()) and tt(container.end()) are said to
hi(template: statements (not) depending on type parameters)
em(depend on template type parameters). The compiler, not having seen
tt(container)'s interface, cannot check whether tt(container) will actually
have members tt(begin()) and tt(end()) returning input iterators, as required
by tt(std::accumulate).
On the other hand, tt(std::accumulate()) itself is a function call which
is independent of any template type parameter. Its em(arguments) are dependent
of template parameters, but the function call itself isn't. Statements in a
template's body that are independent of template type parameters are said
em(not to depend on template type parameters).
When the compiler reads a template definition, it will verify
the syntactical correctness of all statements not depending on template type
parameters. I.e., it must have seen all class definitions, all type
definitions, all function declarations etc., that are used in the statements
not depending on the template's type parameters. If this condition isn't met,
the compiler will not accept the template's definition. Consequently, when
defining the above template, the header file tt(numeric) must have been
included first, as this header file declares tt(std::accumulate()).
On the other hand, with statements depending on template type parameters
the compiler cannot perform these extensive checks, as it has, for example,
no way to verify the existence of a member tt(begin()) for the as yet
unspecified type tt(Container). In these cases the compiler will perform
superficial checks, assuming that the required members, operators and types
will eventually become available.
The location in the program's source where the template is instantiated is
hi(template: point of instantiation)
hi(point of instantiation) called its em(point of instantiation). At
the point of instantiation the compiler will deduce the actual types of the
template's type parameters. At that point it will check the syntactical
correctness of the template's statements that depend on template type
parameters. This implies that em(only at the point of instantiation) the
required declarations must have been read by the compiler. As a
i(rule of thumb),
make sure that all required declarations (usually: header files) have been
read by the compiler at every point of instantiation of the template. For the
template's definition itself a more relaxed requirement can be
formulated. When the definition is read only the declarations required for
statements em(not) depending on the template's type parameters must be known.
|