7

下面的代码用 gcc 和 clang 编译得很好。

template <typename T>
struct identity
{
    typedef T type;
};

template <typename T>
void foo(typename identity<T>::type);

template <typename T>
void foo(T);

int main()
{
    foo<int>(0);
}

看起来重载解决方案正在选择第一个重载(那个identity<T>::type)。

有人可以解释为什么重载不是模棱两可的吗?据我所知,它们之间的唯一区别是第一个参数是非推导上下文,而第二个参数不是,但是由于我明确提供了模板参数,所以我不不明白为什么这很重要。

4

1 回答 1

7

两种重载都是可行的,但前者比后者更专业,因此它被重载决议选中。

根据 C++11 标准关于重载决议的第 13.3.3/1 段:

[...] 一个可行函数F1被定义为比另一个可行函数更好的函数, F2如果对于所有参数iICSi(F1)不是比 , 更差的转换序列ICSi(F2),然后

— 对于某些参数 j,ICSj(F1)是比 更好的转换序列ICSj(F2),或者,如果不是,

— 上下文是通过用户定义的转换(见 8.5、13.3.1.5 和 13.3.1.6)和从 F1 的返回类型到目标类型(即被初始化的实体的类型)的标准转换序列进行的初始化是比从返回类型F2到目标类型的标准转换序列更好的转换序列。[ ... ] 或者,如果不是这样,

F1是一个非模板函数并且F2是一个函数模板特化,或者,如果不是,

F1andF2是函数模板特化,根据 14.5.6.2 中描述的部分排序规则,函数模板 forF1比模板 for 更特化。F2

第 14.5.6.2/2 段概述了确定两个功能模板中哪一个比另一个更专业的过程:

部分排序通过依次转换每个模板(参见下一段)并使用函数类型执行模板参数推导来选择两个函数模板中的哪一个比另一个更专业。推演过程确定模板中的一个是否比另一个更专业。如果是这样,更专业的模板是部分排序过程选择的模板。

于 2013-05-26T22:32:47.563 回答