函数模板调用规则
内容简介
函数模板不是简单的“万能函数”。当普通函数、函数模板、函数模板重载同时存在时,编译器会按匹配程度选择调用哪个函数。
核心规则
- 普通函数和函数模板都能匹配时,通常优先调用普通函数。
- 可以通过空模板参数列表
<>强制调用模板。 - 函数模板也可以重载。
- 如果函数模板匹配更精确,可能优先调用函数模板。
- 自动类型推导时,模板参数必须能推导出一致类型。
用法
普通函数允许隐式类型转换:
int add(int a, int b)
{
return a + b;
}
int a = 10;
char c = 'c';
std::cout << add(a, c) << '\n'; // c 转成 int函数模板自动推导时不做这种统一转换:
template <typename T>
T add_template(T a, T b)
{
return a + b;
}
int a = 10;
char c = 'c';
// add_template(a, c); // 错误:T 无法同时是 int 和 char
add_template<int>(a, c); // 正确:显式指定 T 为 int
add_template<char>(a, c); // 正确:显式指定 T 为 char普通函数和模板函数的选择:
void print(int a, int b)
{
std::cout << "normal\n";
}
template <typename T>
void print(T a, T b)
{
std::cout << "template\n";
}
int x = 1;
int y = 2;
print(x, y); // normal
print<>(x, y); // template,强制调用模板
char m = 'a';
char n = 'b';
print(m, n); // template,因为模板匹配更精确最佳代码实践
- 简单场景直接让编译器自动推导。
- 自动推导失败或语义需要统一类型时,显式指定模板参数。
- 模板和普通函数同时存在时,要有明确目的,避免让读者猜调用结果。
- 复杂重载场景尽量用更清楚的函数名或 concepts 限制类型。
错误用法
template <typename T>
void process(T value);
void process(int value);
process(1); // 初学者容易以为一定调用模板,实际普通函数更优先注意事项
- “模板更通用”不代表“模板总是被调用”。
- 调用规则是理解 STL 算法、泛型工具和重载解析的基础。
- 这部分和 cpp模板特化与局限性、cpp常用模板工具 强相关。