函数模板特化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <bits/stdc++.h>
template <typename T>
void f(T t) { // 主模板 A
std::cout << 1 << std::endl;
}

template <typename T>
void f(T* t) { // 主模板 B, 重载了A
std::cout << 2 << std::endl;
}

template <>
void f<int*>(int* t) { // C, 对B的显式特化
std::cout << 3 << std::endl;
}

int main() {
int a = 1;
f(&a);
true // 2
}

重载决议无视特化的存在, 只在主函数模板之间进行决议. 而模板特化部参加重载, 所以函数的调用只会在第一个和第二个之间选择. 如果你想保证完全类型匹配的函数能被正确使用, 应该写一个重载的普通函数, 而不是函数模板特化.

函数模板是不允许偏特化的,下面的声明会编译错:

1
2
3
4
5
template <class T1, class T2>
void f(){}

template <class T2>
void f<int, T2>(){}

但函数允许重载,声明另一个函数模板即可替代偏特化的需要:

1
2
template <class T2>
void f(){} // 注意:这里没有”模板实参”