Object-oriented programming和generic programming处理的是类似的问题,
那就是——未知的数据类型。
前者处理的是运行时的未知,后者处理的是编译时的未知。
vector、迭代器、算法等,都属于generic program,而templates是generic编程的基础。
如果我们想设计一个generic类型,比如vector,或者编写一个generic函数,比如find,
此时templates就是我们的blueprint。
16.1 Defining a Template
----------------------------------------------------------------
函数模板是一个公式,我们可以使用它产生特定类型的函数版本,
比如:
template <typename T>
int compare(const T &v1, const T &v2)
{
if (v1 < v2)
return -1;
if (v1 > v2)
return 1;
return 0;
}
而它们在运行的时候所产生的version,被称为模板的实例化(instantiation)。
下面的表达式不合法:
template <typename W, U> W calc(const W &t1, const U &u1);
需要修改为:
template <typename W, class U> W calc(const W &t1, const U &u1);
另外,template还可以用来表示某一类型的value值:
template <unsigned N, unsigned M>
int compare(const char (&p1)[N], const char (&p2)[M])
{
return strcmp(p1, p2);
}
这样的template参数,我们称之为nontype,它可以是int、指针、lvalue的引用、函数类型,
但是它必须是一个constant表达式,必须具备static lifetime。
因为template的类型必须要在编译时被确定,而不是运行时。
* 函数参数in the template,必须是references to const。
* 函数体内的test,仅仅使用了“<”。
使用references to const,我们就可以保证函数可以运行在不能被copy的对象上,
虽然到目前为止,除了unique_ptr和IO类型外,大部分数据类型都可以被copy。
另外,运用在大对象时,它能跑得快点。
除了函数模板,还有类模板。
某些时候,typename和class在模板里面的含义是一样的,但是为了方便起见,统一使用前者吧!
如果类模板的构造函数里面,有模板变量,那么我们必须使用尖括号来指定类型:
template <typename T = int> class Numbers {
public:
Numbers(T v = 0): val(v) {}
private:
T val;
};
int main(int argc, char *argv[])
{
Numbers<long double> lots;
Numbers<> aver;
}
(a) template <typename T, U, typename V> void f1(T, U, V);
错误,模板的参数列表必须每个单独有typename。
(b) template <typename T> T f2(int &T);
错误,T不可复用为变量名。
(c) inline template <typename T> T foo(T, unsigned int*);
错误,inline关键字必须在template之后。
(d) template <typename T> f4(T, T);
错误,缺少返回值。
(e) typedef char Ctype;
template <typename Ctype> Ctype f5(Ctype a);
正确,模板参数会覆盖外面的其他name。
由于模板在使用时会被实例化,因此两个单独的源文件使用相同参数的相同模板时,它们会被分别实例化。
当项目非常大时,实例化的资源就很多了,为了避免这个问题,我们可以使用explicit instantiation:
extern template declaration;
template declaration;
16.2 Template Argument Deduction
----------------------------------------------------------------
模板函数一般不做类型转换,而是直接产生另外一个实例。
除了以下两种情况:
* const conversions.
* Array- or function-to-pointer conversions.
因为自动类型转换的情况非常少,因此我们尽量不要让编译器产生困惑。
16.3 Overloading and Templates
----------------------------------------------------------------
16.4 Variadic Templates
----------------------------------------------------------------
模板有可变参数,函数也有。
16.5 Templates Specializations
----------------------------------------------------------------
其实从前一小节开始,阅读已经有些困难了!
高阶内容留到对C++有足够经验的时候再学习。本学习笔记结束,算是C++正式入门啦~
今后开始了解OpenCV,Good Luck!
用户593939 2016-5-17 22:29