1. Berdasarkan Meyers β€œEfektif dan modern c ++” - inferensi tipe template

Selamat siang, pembaca yang budiman!


Artikel ini adalah yang pertama dari serangkaian artikel abstrak yang akan saya tulis ketika saya membaca buku Scott Meyers, Effective and Modern c ++. Setiap artikel ini akan memiliki direktori terpisah dalam proyek yang khusus dibuat di github.com dengan contoh-contoh penggunaan fitur dan teknik yang dijelaskan.


Inferensi Jenis Template


Desain yang sukses adalah ketika konsumen tidak tahu cara kerja perangkat, tetapi semuanya cocok untuknya.


Kesimpulan dari tipe templat adalah ketika ada fungsi templat, misalnya, dan dipanggil tanpa kurung templat dan sudut. Pada saat yang sama, kompiler menebak tipe apa yang perlu digunakan dalam objek fungsi tertentu.


Meyers membagi tipe - "T" , yang ditampilkan dan tipe - "ParamType" , yang ditentukan oleh pemrogram dalam definisi parameter.


1. Tampilan parameter - tautan atau penunjuk


Untuk memahami aturan derivasi dengan cepat, saya akan merefleksikannya dalam bentuk templat:


tipe input -> tipe, parameter -> tipe keluaran [, tipe-akhir parameter ]


Contoh dengan tautan:


template<typename T> //   T void func(T& param) //   - T& int x = 0; //   int func(x); 

Ketika tipe T diturunkan, referensialitas (*, &) dibuang karena sudah ditunjukkan ketika mendefinisikan fungsi, seolah-olah itu berarti "Anda melewatkan apa pun di sana, kami akan menganggap bahwa ini bukan tautan, karena referensialitas sudah ditambahkan di tempat konsumsi - dalam fungsi kami f "


Dengan prinsip yang sama, konstanta dibuang jika ditentukan dalam parameter fungsi. Pada tautan, petunjuk, keteguhan, seolah-olah, topeng eksklusif dikenakan.


Skema Penarikan


 //   int β€”> (T & param) β€”> int; const int β€”> (T & param) β€”> const int; const int & β€”> (T & param) β€”> const int //   int β€”> (const T & param) β€”> int; const int β€”> (const T & param) β€”> int; const int & β€”> (const T & param) β€”> int; //   int * β€”> (T * param) β€”> int; const int β€”> (T * param) β€”> const int; const int * β€”> (T * param) β€”> const int; //   int * β€”> (const T * param) β€”> int; const int β€”> (const T * param) β€”> int; const int * β€”> (const T * param) β€”> int; 

2. Jenis argumen - referensi universal


Scott menyebutkan bahwa tautan universal akan dipertimbangkan nanti, jadi aturan untuk parameter yang ia bagi di sini menjadi nilai dan nilai hanya perlu diingat dengan sedikit pemikiran.


 template<typename T> void func(const T&& param) 

Aturan Inferensi untuk nilai lebih


Scott mengklaim, ini adalah satu-satunya kasus di mana T adalah output sebagai referensi.
Dalam contoh berikut, tipe parameter dalam deskripsi fungsi adalah referensi nilai universal . Dapat dilihat bahwa T ditampilkan sebagai tautan atau tautan konstan, tergantung
dari argumen input, tipe parameter param itu sendiri juga merupakan referensi dalam kasus ini.


 lvalue int β€”> (T &&param) β€”> int &, param - int& lvalue const int β€”> (T &&param) β€”> const int &, param - const int& lvalue const int & β€”> (T &&param) β€”> const int &, param - const int& 

Jenis parameter itu sendiri juga diganti. Saya pikir ini disebabkan oleh fakta bahwa bahasa tidak dapat mempertimbangkan variabel-nilai yang dialokasikan di suatu tempat di atas yang dapat dipindahkan lebih lanjut. Kami akan mencari tahu nanti ketika kami sampai ke tautan universal.
Untuk memverifikasi bahwa T benar-benar sebuah referensi tipe, saya menulis T myVar di badan fungsi templat, yang T ini ditampilkan dan diharapkan menerima pesan - "dideklarasikan sebagai referensi tetapi tidak diinisialisasi" - tautan :)


Aturan Inferensi untuk nilai


Aturan "normal" pada ayat 1 berlaku.


 rvalue int β€”> (T &&param) β€”> int, param - int&& 

Sudah jelas bahwa referensi universal "dimasukkan" hanya untuk nilai-sementara objek, dalam kasus lain, ketika argumen bukan referensi universal, nilai, nilai tidak dibedakan


3. Lewati nilai (seperti apa adanya)


Ketika melewati nilai, keteguhan dan referensialitas dari argumen asli dibuang sebagai tidak perlu karena ini adalah objek independen yang sama sekali baru, mengapa mereka membutuhkan kualifikasi dari apa yang mereka tidak terhubung?


 int β€”> (T param) β€”> int const int β€”> (T param) β€”> int const int & β€”> (T param) β€”> int //       ,     const char * const β€”> (T param) β€”> const char * 

Saya kira kombinasi gila dan tidak logis lainnya akan menyebabkan kesalahan kompilasi, hampir selalu, ternyata, pekerjaan kompiler dapat dimengerti, Anda hanya perlu mendengarkan penjelasan ini sekali saja.

Source: https://habr.com/ru/post/id414233/


All Articles