模板参数分为类型形参与非类型形参。
类型形参:出现在模板参数列表中,跟在class或者typename之类的参数类型名称。
非类型形参:就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用。
就比如说我们需要一个动态数组的时候:
template
class Arr
{
private:T a[N];
};
注意:
1️⃣ 浮点数、类对象以及字符串是不允许作为非类型模板参数的。
2️⃣ 非类型的模板参数必须在编译期就能确认结果。
class Stu
{
public:Stu(const char* name, int age): _age(age){strcpy(_name, name);}bool operator<(Stu& s){return _age < s._age;}
private:char _name[5];int _age;
};template
bool Less(T a, T b)
{return a < b;
}int main()
{Stu s1("a", 10), s2("b", 20);cout << Less(s1, s2) << endl;return 0;
}
但是如果要这么比较:
cout << Less(&s1, &s2) << endl;
这里就需要模板的特化
template
bool Less(T a, T b)
{return a < b;
}// Less 的特化
template <>
bool Less(Stu* a, Stu* b)
{return *a < *b;
}
要注意这个是上面模板函数的特化,不能单独写。
全特化即是将模板参数列表中所有的参数都确定化。
template
class A
{
public:A(){cout << "" << endl;}
private:T1 a;T2 b;
};template<>
class A
{
public:A(){cout << "" << endl;}
};int main()
{A a;A b;return 0;
}
template
class A
{
public:A(){cout << "" << endl;}
private:T1 a;T2 b;
};// 偏特化
template
class A
{
public:A(){cout << "" << endl;}
};
当我们在头文件声明模板函数,而在源文件定义模板函数
// a.h
template
T Add(const T& left, const T& right);
// a.cpp
template
T Add(const T& left, const T& right)
{return left + right;
}
这样运行起来会出现链接错误:
在源文件编译的时候,Add函数没有实例化,因此没有生成函数。但是编译器链接的时候会去找函数的地址,但是函数没有实例化没有地址,所以会出现链接错误。
解决办法:
1️⃣ 将声明和定义放到一个文件 “xxx.hpp” 里面或者xxx.h其实也是可以的。推荐使用这种。
2️⃣ 模板定义的位置显式实例化。这种方法不实用,不推荐使用