Jenis dan ambiguitas pengembalian otomatis

20

Saya memiliki fungsi template yang kelebihan beban:

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;
}

Jika saya menyebutnya seperti ini:

auto a = overMax(4, 7.2); // uses first template
auto b = overMax<double>(4, 7.2); // uses second template

semuanya bekerja dengan sempurna, tetapi

auto c = overMax<int>(4, 7.2); // error

menyebabkan panggilan ambigu.

Mengapa begitu dengan int , dan OK jenis apa yang lain?

penguat
sumber
4
Saya pikir ... .... Cara kompiler melihatnya, adalah: dengan int, apakah Anda menentukan typename RTatau typename T1? Karena 4juga merupakan int, bisa jadi keduanya. Dengan double, 4tidak secara langsung cocok dengan jenisnya double, jadi kelebihan kedua lebih disukai.
ChrisMM
Ini terlihat agak cerdik bagi saya karena Anda semacam kelebihan pada tipe kembali tetapi dengan template yang memiliki jumlah parameter yang berbeda.
Borgleader

Jawaban:

25

RTtidak dapat dikurangkan, jadi ketika tidak menyediakannya, hanya template<typename T1, typename T2> auto overMax(T1 a, T2 b)dapat dipanggil.

Ketika Anda (sebagian) memberikan satu argumen templat, kedua metode tersebut layak,

tetapi tergantung dari argumen, seseorang dapat menjadi kandidat yang lebih baik:

  • Untuk auto b = overMax<double>(4, 7.2); // uses second template

    Keduanya overMax<double, int, double>dan overMax<double, double>layak.
    Tapi overMax<double, int, double>ini sama persis
    sedangkan overMax<double, double>membutuhkan intuntuk doublekonversi.

  • Untuk auto c = overMax<int>(4, 7.2); // Ambiguous call

    Keduanya overMax<int, int, double>dan overMax<int, double>layak.
    Tetapi tidak ada pasangan yang lebih baik atau lebih terspesialisasi, sehingga panggilannya ambigu.

Jarod42
sumber
mengapa tak satu pun dari mereka yang lebih baik? Apakah saya benar bahwa dalam kasus pertama overMax <int> (4, 7.2); akan menyebabkan konversi 7,2 ke int . Dan dalam kasus kedua hasil yang dikembalikan, yang awalnya ganda , akan dikonversi ke int karena <int> eksplisit ?
penguat
1
@amplifier: overMax<int>(4, 7.2)akan dalam kasus pertama T1=int(disediakan), T2=double(disimpulkan) dan dalam kasus kedua RT=int(disediakan), T1=int, T2=double(disimpulkan). Definisi konten dari kedua metode tidak digunakan untuk memilih kelebihan muatan.
Jarod42
bagi saya, kasus kedua cocok, karena ada konversi tipe pengembalian untuk yang pertama dan tidak ada konversi sama sekali untuk yang kedua, bukan?
penguat
hmmm ... konversi tipe kembali tidak berperan ... maka, ya, kedua panggilan setara dari sudut pandang ini
penguat