C++ 模版函数重载匹配规则

#1. 非模板函数优先

如果有非模版函数,优先调用非模版函数。

1
2
3
4
void foo(int x) {}          // 非模板函数
template <typename T> void foo(T x) {} // 模板函数

foo(5); // 调用非模板函数 void foo(int)

#2. 更特化的模板优先

如果多个模板可行,编译器选择更特化(更具体)的模板版本。

1
2
3
4
5
template <typename T> void foo(T x) {}      // 通用模板
template <typename T> void foo(T* x) {} // 更特化的指针版本

int x = 0;
foo(&x); // 调用指针版本的 f<int*>(int*)

#3. 精确匹配优于类型转换

若参数匹配需要隐式类型转换,模板生成的精确匹配版本优先于需要转换的非模板函数。

1
2
3
4
void foo(double x) {}        // 非模板函数,需要 int→double 转换
template <typename T> void foo(T x) {} // 模板生成 f<int>(int)

foo(5); // 调用模板函数 f<int>(int)(无需转换)

#4. 引用和值类型的优先级

引用类型(尤其是 T&& 万能引用)可能影响匹配:

1
2
3
4
5
template <typename T> void foo(T&& x) {}  // 万能引用
void foo(int x) {} // 非模板函数

foo(5); // 调用非模板函数(精确匹配)
foo(x); // x 是 int 变量,调用模板函数 f<int&>(int&)(更匹配左值)

#5. 若存在多个同样好的匹配,编译器报错:

1
2
3
4
5
template <typename T> void f(T x) {}
template <typename T> void f(T* x) {}

int x = 0;
f(&x); // 歧义:T=int*(通用模板) vs. T=int(指针模板)

#6. 可变参数模板优先级最低

1
2
3
4
template <typename... Args> void f(Args... args) {}  // 最低优先级
template <typename T> void f(T x) {}

f(5); // 调用非可变参数模板 f<int>(int)