以一个普通函数模板为例:
template <typename A, typename B>
void f(A a, B b) {
}
template <typename A>
void f(A a, int b) {
} //这个写法有点奇怪,我认为这里是重载,跟偏特化有迷惑性
void f(char a, int b) {
} //普通的函数
template <>
void f(char a, int b) {
} //这跟上面的f是同一个意思,不属于全特化
template <>
void f<char,int>(char a, int b) {
} //全特化。一定是在f后面用<>指明了类型
template <typename A, typename B>
void f(A* a, B b) {
} //函数重载,更匹配参数类型第一个是指针类型的
template <typename B>
void f<int*,B>(int* a, B b) {
} //错误,偏特化写法,函数类型不能偏特化
全特化和偏特化的写法一定是f后面跟<>,当然这里f是函数,函数不支持偏特化。
接下来以类为例:
template <typename A, typename B>
class Test {
public:
void func(A a, B b) {
cout << "func 0 " << endl;
}
};
template <>
class Test<int,int> {
public:
void func(int a, int b) {
cout << "func 1 " << endl;
}
}; //全特化
class Test {
public:
void func(int a, int b) {
cout << "func 2 " << endl;
}
}; //普通的类,但是如果和前面的template <typename A,typename B> class Test放一个头文件则会报错。(“Test”: 非类 模板 已经声明为类 模板)
template <typename A>
class Test{
public:
void func(A a, int b) {
}
}; //正常单独声明没错,但是如果前面的template <typename A,typename B> class Test 放一个头文件则会报错。(“Test”: 模板 参数太少)
template <typename A>
class Test<A, int> {
public:
void func(A a, int b) {
}
}; //偏特化,指定了一部分参数,参数个数的偏特化
template <typename A, typename B>
class Test<const A*, B&> {
public:
void func(A a, B b) {
}
}; //偏特化,取值范围的偏特化
结论:
对一个普通的函数或者类模板:
template <typename A, typename B>
void f(A a, B b) {
}
或者
template <typename A, typename B>
class Test {
public:
void func(A a, B b) {
}
};
如果后续的定义:
1.以template<>起头,且函数或者类后面需要在<>中显式指明类型 。
则为全特化。函数和类都可以。
2.如果非template <> 起头,且函数或者类后面没有跟<>。
如果是函数,则是重载,是类,则会报错。
2.如果非template <> 起头,且函数或者类后面有跟<>。
如果是函数,则报错,函数不能偏特化。如果是类,则是偏特化。