У меня перегружена функция шаблона:
template<typename T1, typename T2>
auto overMax(T1 a, T2 b)
{
std::cout << __FUNCSIG__ << std::endl;
return b < a ? a : b;
}
template<typename RT, typename T1, typename T2>
RT overMax(T1 a, T2 b)
{
std::cout << __FUNCSIG__ << std::endl;
return b < a ? a : b;
}
Если я назову это так:
auto a = overMax(4, 7.2); // uses first template
auto b = overMax<double>(4, 7.2); // uses second template
все работает отлично, но
auto c = overMax<int>(4, 7.2); // error
вызывает неоднозначный вызов.
Почему это так с int , и хорошо, какие другие типы?
int
, вы указываетеtypename RT
илиtypename T1
? Так как4
это тожеint
может быть. Сdouble
,4
не соответствует напрямую типуdouble
, поэтому вторая перегрузка предпочтительнее.Ответы:
RT
не подлежит вычету, поэтому, если его не предоставить,template<typename T1, typename T2> auto overMax(T1 a, T2 b)
можно вызвать только .Когда вы (частично) предоставляете один аргумент шаблона, оба метода являются жизнеспособными,
но в зависимости от аргумента, один может быть лучшим кандидатом:
За
auto b = overMax<double>(4, 7.2); // uses second template
Оба
overMax<double, int, double>
иoverMax<double, double>
жизнеспособны.Но
overMax<double, int, double>
это точное совпадение ,тогда как
overMax<double, double>
требуетсяint
дляdouble
преобразования.За
auto c = overMax<int>(4, 7.2); // Ambiguous call
Оба
overMax<int, int, double>
иoverMax<int, double>
жизнеспособны.Но ни один из них не является лучшим или более специализированным, поэтому вызов неоднозначен.
источник
overMax<int>(4, 7.2)
будет в первом случаеT1=int
(при условии),T2=double
(вывод) и во втором случаеRT=int
(при условии),T1=int, T2=double
(вывод). Содержимое определения обоих методов не используется для выбора перегрузки.