C++ template (尖括号)

from: C++ primer

16.1. Template Definitions
Let's imagine that we want to write a function to compare two values and indicate whether
the first is less than, equal to, or greater than the second. In practice, we'd want to define
several such functions, each of which could compare values of a given type. Our first
attempt might be to define several overloaded functions:

// returns 0 if the values are equal, -1 if v1 is smaller, 1 if v2 is smaller
int compare(const string &v1, const string &v2)
{
  if (v1 < v2) return -1;
  if (v2 < v1) return 1;
  return 0;
}
int compare(const double &v1, const double &v2)
{
  if (v1 < v2) return -1;
  if (v2 < v1) return 1;
  return 0;
}

These functions are nearly identical: The only difference between them is the type of their
parameters. The function body is the same in each function.
Having to repeat the body of the function for each type that we compare is tedious and
error-prone. More importantly, we need to know in advance all the types that we might
ever want to compare. This strategy cannot work if we want to be able to use the function
on types that we don't know about.

16.1.1. Defining a Function Template
Rather than defining a new function for each type, we can define a single function
template. A function template is a type-independent function that is used as a formula for
generating a type-specific version of the function. For example, we might write a function
template named compare, which would tell the compiler how to generate specific versions
of compare for the types that we want to compare.
The following is a template version of compare:

// implement strcmp-like generic compare function
// returns 0 if the values are equal, 1 if v1 is larger, -1 if v1 is smaller
template <typename T>
int compare(const T &v1, const T &v2)
{
  if (v1 < v2) return -1;
  if (v2 < v1) return 1;
  return 0;
}

 
A template definition starts with the keyword template followed by a template parameter
list, which is a comma-separated list of one or more template parameters bracketed by
the less-than (<) and greater-than (>) tokens.
The template parameter list cannot be empty.

Template Parameter List
The template parameter list acts much like a function parameter list. A function parameter
list defines local variable(s) of a specified type but leaves those variables uninitialized. At
run time, arguments are supplied that initialize the parameters.
Analogously, template parameters represent types or values we can use in the definition
of a class or function. For example, our compare function declares one type parameter
named T. Inside compare, we can use the name T to refer to a type. Which actual type T
represents is determined by the compiler based on how the function is used.
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. We'll see more about nontype parameters in Section 16.1.5 (p.
632). A type parameter is defined following the keyword class or typename. For example,
class T is a type parameter named T. There is no difference between class and typename
in this context.

Using a Function Template
When we use a function template, the compiler infers what template argument(s) to bind
to the template parameter(s). Once the compiler determines the actual template
argument(s), it instantiates an instance of the function template for us. Essentially, the
compiler figures out what type to use in place of each type parameter and what value to
use in place of each nontype parameter. Having deduced the actual template arguments,
it generates and compiles a version of the function using those arguments in place of the
corresponding template parameters. The compiler takes on the tedium of (re)writing the
function for each type we use.
Given the calls

int main ()
{
  // T is int;
  // compiler instantiates int compare(const int&, const int&)
  cout << compare(1, 0) << endl;
  // T is string;
  // compiler instantiates int compare(const string&, const string&)
  string s1 = "hi", s2 = "world";
  cout << compare(s1, s2) << endl;
  return 0;
}

 
the compiler will instantiate two different versions of compare. The compiler will create
one version that replaces T by int and a second version that uses string in place of T.

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&);

 

16.1.2. Defining a Class Template
Just as we can define function templates, we can also define class templates.
To illustrate class templates, we'll implement our own version of the standard
library queue (Section 9.7, p. 348) class. User programs ought to use the
standard queue class, not the one we define here.
Our Queue must be able to hold objects of different types, so we'll define it as a class
template. The operations our Queue will support are a subset of the interface of the
standard queue:
  • push to add an item to the back of the queue
  • pop to remove the item at the head of the queue
  • front to return a reference to the element at the head of the queue
  • empty to indicate whether there are any elements in the queue
We'll look at how we might implement our Queue in Section 16.4 (p. 647), but we can start
by defining its interface:

template <class Type> class Queue {
public:
  Queue ();
  // default constructor
  Type &front ();
  // return element from head of Queue
  const Type &front () const;
  void push (const Type &); // add element to back of Queue
  void pop();
  // remove element from head of Queue
  bool empty() const;
  // true if no elements in the Queue
  private:
  // ...
};

 
A class template is a template, so it must begin with the keyword template followed by a
template parameter list. Our Queue template takes a single template type parameter
named Type.
With the exception of the template parameter list, the definition of a class template looks
like any other class. A class template may define data, function, and type members; it may
use access labels to control access to those members; it defines constructors and
destructors; and so on. In the definition of the class and its members, we can use the
template parameters as stand-ins for types or values that will be supplied when the class
is used.
For example, our Queue template has one template type parameter. We can use that
parameter anywhere a type name can be used. In this template definition, we use Type to
name the return type from the overloaded front operations and as the parameter type for
the push operation.

Using a Class Template
In contrast to calling a function template, when we use a class template, we must explicitly
specify arguments for the template parameters:

  Queue<int> qi;          // Queue that holds ints
  Queue< vector<double> > qc;  // Queue that holds vectors of doubles
  Queue<string> qs;        // Queue that holds strings

The compiler uses the arguments to instantiate a type-specific version of the class.
Essentially, the compiler rewrites our Queue class replacing Type by the specified actual
type provided by the user. In this case, the compiler will instantiate three classes: a
version of Queue with Type replaced by int, a second Queue class that uses
vector<double> in place of Type, and a third that replaces Type by string.

原文链接: https://www.cnblogs.com/zhengzhibogd/archive/2013/01/22/2871003.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    C++ template (尖括号)

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/76346

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月9日 下午5:27
下一篇 2023年2月9日 下午5:27

相关推荐