由于功能模板的部分排序,以下内容似乎是明确的:
template <class T> void f(T*) {
cout << "T*" << endl;
}
template <class T> void f(const T*) {
cout << "const T*" << endl;
}
int main(){
int *p = nullptr;
f(p);
}
在两种情况下, T
都推导为int
,并且两个专业都可行,第二个要求从int *
到const int*
的隐式资格转换。两者都被添加到过载集中。
为了找到最佳可行的功能,我们转向部分排序。我们为每种类型合成新的类型,并获得void f(X*)
和void f(const Y*)
。然后我们在两者之间进行类型推导。 [temp.deduct.partial]¶8:
使用所得类型P和A,然后按17.8.2.5中所述进行推导。 (...)如果给定类型的推导成功,则认为自变量模板中的类型至少与自参数模板中的类型一样专业。
在给定template <class T> void f(T*)
的情况下,const Y*
的扣除是否成功?是的,使用T=const Y
。
在给定template <class T> void f(const T*)
的情况下,X*
的扣除是否成功?是的,使用T=X
(需要隐式资格转换)。
因此,X和Y至少彼此一样专门化,这意味着两个专门化都至少与另一个同样专门化,这意味着调用是不明确的。
除了不是,所以我在上面哪里出错了?
答案 0 :(得分:1)
我找出了哪里出了问题:
为了找到最佳可行的功能,我们转向部分排序。
不,我们没有。为了找到最佳可行的功能,我们按顺序进行[over.match.best]中的步骤。部分排序只是该列表上的一个点,实际上我们从来没有得到过,因为最佳的可行函数是在列表的上一步找到的(对于某些参数j,,ICSj(F1)比ICSj(F2))。
这两个专业确实确实是同等专业的,但这并不重要,因为我们从不首先使用偏序。
答案 1 :(得分:0)
template <class T> void f(const T*)
确实比template <class T> void f(T*)
更专业,但后者是完全匹配。
如果您查看overload_resolution#best_viable_function:
最佳可行功能:
1)F1至少有一个参数,其隐式转换要好于F2的相应隐式转换。
[..]
5),或者如果不是这样,则F1和F2都是模板专业化,而F1根据模板专业化的部分排序规则更专业化