定义模板时, 使用关键字typename还是class没有区别,两个都可以用。
下例是函数模板的定义及使用,可以看出,函数模板的调用方式同一般函数:
// 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 (v1 < v2) return -1; return 0; } int main () { // 编译器实例化为int compare(const int&, const int&) cout << compare(1, 0) << endl; // 编译器实例化为int compare(const string&, const string&) string s1 = "hi", s2 = "world"; cout << compare(s1, s2) << endl; return 0; }对于内联函数模板,inline关键字必须位于模板参数列表和函数返回类型的中间。
// OK: inline specifier follows template parameter list template <typename T> inline T min(const T&, const T&); // !!! ERROR: inline 不能放在template关键字之前 inline template <typename T> T min(const T&, const T&);类模板的定义形式及使用如下所示:
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: // ... }; int main() { Queue<int> qi; // Queue that holds ints Queue< vector<double> > qc; // Queue that holds vectors of doubles Queue<string> qs; // Queue that holds strings return 0; }不同于一般函数和类定义,对于模板,编译器要求看到调用模板函数或模板类的成员函数时,也要求能看到定义。C++定义了两种编译模板代码的模型:包含编译模型(Inclusion Compilation Model) 和单独编译模型(Separate Compilation Model), 以支持声明和实现,或定义和实现分别放在头文件和源文件中的项目组织形式。
否则,要通过编译,模板的实现必须放在头文件中。
这种编译模型,所有的编译器都支持。
// 头文件 utlities.h #ifndef UTLITIES_H // header gaurd (Section 2.9.2, p. 69) #define UTLITIES_H template <class T> int compare(const T&, const T&); // other declarations #include "utilities.cc" // get the definitions for compare etc. #endif ---------------------------------------------------------------- // 源文件 utlities.cc template <class T> int compare(const T &v1, const T &v2) { if (v1 > v2) return 1; if (v1 < v2) return -1; return 0; } // other definitions用VS2010测试:
//file: my_template.h #ifndef MY_TEMPLATE_H #define MY_TEMPLATE_H template<typename T> int compare(const T&, const T&); #include "my_template.cpp" # Most import line for build #endif ----------------------------------------------------- //file: my_template.cpp #include "stdafx.h" // 注意,这里不能加 #include "my_template.h", 加了就无法编译通过。 template<typename T> int compare(const T& v1, const T& v2) { if (v1 > v2) return 1; if (v1 < v2) return -1; return 0; } ----------------------------------------------------- // file with main: #include "stdafx.h" #include "my_template.h" #include <iostream> using std::cout; using std::endl; int _tmain(int argc, _TCHAR* argv[]) { cout << compare(3, 1) << endl; system("pause"); return 0; } // 可以成功执行,输出 1.对于函数模板,这种方法ok。
但是测试中发现,对于模板类,如果加了类似 include “source.cpp” 的指令,会出现“函数模板已经定义”的错误,所以,把模板类的实现也放在头文件中,将是省时省力的做法。
这种编译模型使用了关键字export。
对于函数,只需在源文件中的函数定义前加export关键字。
// the template definition goes in a separately-compiled source file export template <typename Type> Type sum(Type t1, Type t2) /* ...*/对于类,略有不同:
// 头文件 template <class Type> class Queue { ... }; ------------------------------------------------------------- // 源文件 export template <class Type> class Queue; #include "Queue.h" // Queue member definitions由于VS2010 说它不支持export关键字,这种编译模型没测试过。
[1] C++ Primer Chapter 16 Templates and Generic Programming
