Mam przeciążoną funkcję szablonu:
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;
}
Jeśli nazywam to tak:
auto a = overMax(4, 7.2); // uses first template
auto b = overMax<double>(4, 7.2); // uses second template
wszystko działa idealnie, ale
auto c = overMax<int>(4, 7.2); // error
powoduje niejednoznaczne połączenie.
Dlaczego tak jest z int , a jakie inne typy są OK?
int
, czy określasztypename RT
czytypename T1
? Ponieważ4
jest to równieżint
, może być albo. Zdouble
,4
nie pasuje bezpośrednio do typudouble
, więc preferowane jest drugie przeciążenie.Odpowiedzi:
RT
nie można go wydedukować, więc jeśli go nie podasz,template<typename T1, typename T2> auto overMax(T1 a, T2 b)
można go wywołać tylkoGdy (częściowo) podasz jeden argument szablonu, obie metody są wykonalne,
ale w zależności od argumentów można być lepszym kandydatem:
Dla
auto b = overMax<double>(4, 7.2); // uses second template
Oba
overMax<double, int, double>
ioverMax<double, double>
są opłacalne.Ale
overMax<double, int, double>
jest dokładne dopasowanienatomiast
overMax<double, double>
wymagaint
dodouble
konwersji.Dla
auto c = overMax<int>(4, 7.2); // Ambiguous call
Oba
overMax<int, int, double>
ioverMax<int, double>
są opłacalne.Ale żaden nie jest lepszym dopasowaniem ani bardziej wyspecjalizowany, więc połączenie jest niejednoznaczne.
źródło
overMax<int>(4, 7.2)
będzie w pierwszym przypadkuT1=int
(pod warunkiem),T2=double
(wydedukowany), a w drugim przypadkuRT=int
(pod warunkiem),T1=int, T2=double
(wydedukowany). Definicja treści obu metod nie jest używana do wybierania przeciążenia.