1.Template Parameter List
A template parameter can be a type parameter, which represents a type, or a nontype parameter , which represents a constant expression. A nontype parameter is declared following a type specifier. A type parameter is defined following the keyword class or typename.
The only meaning we can ascribe to a template parameter is to distinguish whether the parameter is a type parameter or a nontype parameter. If it is a type parameter, then we know that the parameter represents an as yet unknown type. If it is a nontype parameter, we know it is an as yet unknown value.
2.inline Function Templates
A function template can be declared inline in the same way as a nontemplate function. The specifier is placed following the template parameter list and before the return type. It is not placed in front of the template keyword.// ok: inline specifier follows template parameter list
template <typename T> inline T min(const T&, const T&);
// error: incorrect placement of inline specifier
inline template <typename T> T min(const T&, const T&);
3.Using a Function Template
template <typename T> |
When we called compare on two string s, we passed two string objects, which we initialized from string literals
What would happen if we wrote: compare ("hi", "world")
.该代码会出现编译错误。因为引用的缘故,根据”hi”可将模板形参推断为char[3],根据”world”可将模板形参推断为char[6],T被推断为不同的类型。、
4.Designating Types inside the Template Definition
In addition to defining data or function members, a class may define type members. When we want to use such types inside a
function template, we must tell the compiler that the name we are using refers to a type. We must be explicit because the compiler (and a reader of our program) cannot tell by inspection when a name defined by a type parameter is a type or a value. As an example, consider the following function:template <class Parm, class U>
Parm fcn(Parm* array, U value)
{
Parm: :size_type * p; // If Parm::size_type is a type, then a declaration
// If Parm::size_type is an object, then multiplication
}
We know that size_type must be a member of the type bound to Parm , but we do not know whether size_type is the name of a type or a data member. By default, the compiler assumes that such names name data members, not types. If we want the compiler to treat size_type as a type, then we must explicitly tell the compiler to do so:template <class Parm, class U>
Parm fcn(Parm* array, U value)
{
typename Parm::size_type * p; // ok: declares p to be a pointer
}
5.Question
Write a function template that takes a pair of values that represent iterators of unknown type. Find the value that occurs most frequently in the sequence.template<typename T>
typename T::value_type find_most(T begin, T end)
{
T most_iter;
size_t max_num, num;
map<typename T::value_type, size_t> container;
max_num = 0;
while(begin != end)
{
num = ++container[*begin];
if(num > max_num)
{
max_num = num;
most_iter = begin;
}
++begin;
}
return *most_iter;
}
6. Nontype Template Parameters
The function itself takes a single parameter, which is a reference to an arraytemplate <class T, size_t N> void array_init(T (&parm)[N])
{
for (size_t i = 0; i != N; ++i) {
parm[i] = 0;
}
}
int x[42];
double y[10];
array_init(x); // instantiates array_init(int(&)[42])
array_init(y); // instantiates array_init(double(&)[10])
A template nontype parameter is a constant value inside the template definition. A nontype parameter can be used when constant expressions are required.// Another example: Write a function template that can determine the size of an array.
template<typename T, size_t N>
size_t size(T (&array)[N])
{
return N;
}
7. Writing Generic Programs
The operations performed inside a function template constrains the types that can be used to instantiate the function. It is up to the programmer to guarantee that the types used as the function arguments actually support any operations that are used, and that
those operations behave correctly in the context in which the template uses them.
When writing template code, it is useful to keep the number of requirements placed on the argument types as small as possible.Simple though it is, our compare function illustrates two important principles for writing generic code:
- The parameters to the template are const references.
- The tests in the body use only < comparisons.
By making the parameters const references, we allow types that do not allow copying. Moreover, if compare is called with large objects, then this design will also make the function run faster. we reduce the requirements on types that can be used with our compare function. Those types must support < , but they need not also support > .