Pertimbangkan kode berikut .
struct any
{
template <typename T>
operator T &&() const;
template <typename T>
operator T &() const;
};
int main()
{
int a = any{};
}
Di sini operator konversi kedua dipilih oleh resolusi kelebihan beban. Mengapa?
Sejauh yang saya mengerti, kedua operator disimpulkan operator int &&() const
dan operator int &() const
masing - masing. Keduanya berada di set fungsi yang layak. Membaca [over.match.best] tidak membantu saya mencari tahu mengapa yang terakhir lebih baik.
Mengapa fungsi yang terakhir lebih baik dari yang sebelumnya?
template <typename T> operator T &&() const &&; template <typename T> operator T &() const &;
mendapatkannya untuk memanggil yang pertama.Jawaban:
Operator konversi yang mengembalikan
T&
lebih disukai karena lebih khusus daripada operator konversi yang mengembalikanT&&
.Lihat C ++ 17 [temp.deduct.partial] / (3.2):
dan / 9:
sumber
Operator konversi nilai kembalian yang disimpulkan agak aneh. Tetapi ide intinya adalah bahwa ia bertindak seperti parameter fungsi untuk memilih yang mana yang digunakan.
Dan ketika memutuskan antara
T&&
danT&
yangT&
menang dalam aturan resolusi overload. Ini untuk mengizinkan:bekerja.
T&&
dapat cocok dengan nilai lv, tetapi ketika nilai lv dan referensi universal kelebihan tersedia, nilai l lebih disukai.Operator konversi yang tepat mungkin:
atau bahkan
untuk mencegah perpanjangan seumur hidup yang gagal menggigit Anda.
[MENGGUNTING]
Yang akhirnya tergantung pada aturan "lebih khusus" ketika mengambil kelebihan:
Dengan demikian
operator T&&
tidak setidaknya sama terspesialisasioperator T&
, sementara tidak ada negara aturanoperator T&
tidak setidaknya sama terspesialisasioperator T&&
, jadioperator T&
lebih khusus daripadaoperator T&&
.Template yang lebih khusus memenangkan resolusi kelebihan lebih dari yang lebih sedikit, yang lainnya dianggap sama.
sumber
&&
vs&
diperlakukan ketika memilih kelebihan template, tetapi mencari tahu teks yang tepat akan membutuhkan waktu. .Kami mencoba menginisialisasi
int
dariany
. Proses untuk itu:Cari tahu semua cara kita bisa melakukan itu. Artinya, tentukan semua kandidat kita. Ini berasal dari fungsi konversi non-eksplisit yang dapat dikonversi ke
int
melalui urutan konversi standar ( [over.match.conv] ). Bagian ini mengandung frasa ini:Pilih kandidat terbaik.
Setelah langkah 1, kami memiliki dua kandidat.
operator int&() const
danoperator int&&() const
, keduanya dianggap menghasilkanint
untuk tujuan pemilihan fungsi kandidat. Manakah yang menghasilkan kandidat terbaikint
?Kami memang memiliki tiebreak yang lebih memilih referensi nilai lebih dari referensi nilai ( [over.ics.rank] /3.2.3 ). Kami tidak benar-benar mengikat referensi di sini, dan contohnya ada yang agak terbalik - ini adalah untuk kasus di mana parameternya adalah lvalue vs rvalue referensi.
Jika itu tidak berlaku, maka kita masuk ke tiebreaker [over.match.best] /2.5 dari lebih memilih templat fungsi yang lebih khusus.
Secara umum, aturan praktisnya adalah konversi yang lebih spesifik adalah yang paling cocok. Fungsi konversi referensi nilai lebih spesifik daripada fungsi konversi referensi penerusan, jadi lebih disukai. Tidak ada apa-apa tentang
int
kita menginisialisasi yang membutuhkan nilai (jika kita telah menginisialisasiint&&
, makaoperator T&() const
itu tidak akan menjadi kandidat).sumber
T&&
menang bukan? Ah, tapi kita tidak punya nilai yang terikat. Atau apakah kita? Ketika memilih kandidat kita, beberapa kata pasti telah menentukan bagaimana kita mendapatkanint&
danint&&
, apakah itu mengikat?