在该列表中,只有第二个引入了歧义,因为函数 - 无论它们是否是模板 - 都不能根据返回类型重载。
你可以使用其他两个:
template<typename X> void func(X x, int y);
如果调用的第二个参数是 int 则使用,例如 func("string", 10);
template<class X, class Y, class Z> void func(X x, Y y, Z z);
如果你用三个参数调用 func 将被使用。
我不明白为什么其他一些答案提到模板函数和函数重载不混合。他们当然会这样做,并且有特殊规则如何选择要调用的函数。
14.5.5
函数模板可以是
与其他功能重载
模板和正常
(非模板)函数。一个正常的
功能与 a 无关
函数模板(即,它永远不会
被认为是专业化),
即使它具有相同的名称和类型
作为潜在生成的函数
模板专业化。)
非模板化(或“较少模板化”)重载优先于模板,例如
template <class T> void foo(T);
void foo(int);
foo(10); //calls void foo(int)
foo(10u); //calls void foo(T) with T = unsigned
您的第一个带有一个非模板参数的重载也属于此规则。
在多个模板之间进行选择时,首选更专业的匹配:
template <class T> void foo(T);
template <class T> void foo(T*);
int i;
int* p;
int arr[10];
foo(i); //calls first
foo(p); //calls second
foo(arr); //calls second: array decays to pointer
您可以在标准的同一章节中找到所有规则的更正式的描述(函数模板)
最后,在某些情况下,两个或多个重载会产生歧义:
template <class T> void foo(T, int);
template <class T> void foo(int, T);
foo(1, 2);
这里的调用是模棱两可的,因为两个候选人都同样专业。
您可以使用(例如)boost::disable_if 来消除此类情况的歧义。例如,我们可以指定当 T = int 时,不应将第二个重载作为重载候选:
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
template <class T>
void foo(T x, int i);
template <class T>
typename boost::disable_if<boost::is_same<int, T> >::type
foo(int i, T x);
foo(1, 2); //calls the first
这里库在第二个重载的返回类型中产生“替换失败”,如果 T = int,则将其从重载候选集中删除。
在实践中,您应该很少遇到这样的情况。