模板与泛型编程
一、函数模板
模板定义以关键字template开始,后跟一个模板参数列表,在模板定义中,模板参数列表不能为空。
模板类型参数:类型参数前必须使用class或typename关键字。
非类型模板参数:表示一个值而不是一个类型
数组引用形参:
//&arr两端的括号必不可少 void print(int(&arr)[10]) { for (auto elem : arr) { cout << elem << endl; } }
//用于比较字符串常量 //compare("hi","mom") template<unsigned N,unsigned M> int compare(const char(&p1)[N], const char(&p2)[M]) { return strcmp(p1, p2); }
一个非类型参数可以是一个整型,或者是一个指向对象或函数类型的指针或引用。绑定到非类型整型参数的实参必须是一个常量表达式。绑定到指针或引用非类型参数的实参必须具有静态的生存期。我们不能用一个普通(非static)局部变量或动态对象作为指针或引用非类型模板参数的实参。指针参数也可以用nullptr或一个值为0的常量表达式来实例化。
inline或constexpr说明符放在模板参数列表之后,返回类型之前。
template <typename T> inline T min(const T&, const T&);
inline template <typename T> T min(const T&, const T&);//出错
通常,当我们调用一个函数时,编译器只需要掌握函数的声明。类似地,当我们使用一个类类型的对象时,类定义必须是可用的,但成员函数的定义不必已经出现。因此,我们将类定义和函数声明放在头文件中,而普通函数和类的成员函数的定义放在源文件中。
为了生成一个实例化版本,编译器需要掌握函数模板或类模板成员函数的定义。所以函数模板和类模板成员函数的定义通常放在头文件中。