我试图理解为什么GCC在下面的代码中选择f(char, A<C, 5> &var)
进行重载解析:
template <class C, int N> struct A { };
template <class C> struct A<C, 8> { static_assert(sizeof(C) > 8, "Assertion in A<C,8>"); };
template <class C> struct A<C, 5> { static_assert(sizeof(C) < 8, "Assertion in A<C,5>"); operator A<C,8>&(); };
template <class C> void f(double, A<C,8> &var);
template <class C> void f(char, A<C,5> &var);
int main(void)
{
A<int, 5> a;
f(4., a);
}
有两种可用的重载:
template <class C> void f(double, A<C,8> &var);
4.
完全匹配double
(不需要隐式转换),但第二个参数需要用户定义的转换。所以这个重载:exact match
&amp; user-define conversion
下一个重载,由GCC匹配:
template <class C> void f(char, A<C,5> &var);
4.
要求隐式转换为char
,但与A<C,5>
完全匹配。 GCC是否有理由选择此超载而不是之前的?
有人可以从标准的第13部分找到有关此特定案件的证据吗?任何帮助或评论表示赞赏。谢谢!
答案 0 :(得分:5)
扣除不能成功
template <class C> void f(double, A<C,8> &var);
和A<int, 5>
类型的参数。即没有可能的C
类型可以使A<C,8>
与参数类型A<int,5>
匹配。转换是可能的并不关心扣除。
见[temp.deduct.call] / 4。由于转换构造函数和转换函数可以允许转换,因此无法考虑(所有)转换类型推导。这也可能导致含糊不清。