C ++ 20 memperkenalkan std::common_reference
. Apa tujuannya? Adakah yang bisa memberi contoh menggunakannya?
C ++ 20 memperkenalkan std::common_reference
. Apa tujuannya? Adakah yang bisa memberi contoh menggunakannya?
Jawaban:
common_reference
keluar dari upaya saya untuk datang dengan konseptualisasi iterator STL yang mengakomodasi iterator proxy.
Dalam STL, iterator memiliki dua jenis minat khusus yang terkait: reference
dan value_type
. Yang pertama adalah jenis kembalinya iterator operator*
, dan value_type
merupakan (non-const, non-referensi) jenis elemen dari urutan.
Algoritme umum sering kali perlu melakukan hal-hal seperti ini:
value_type tmp = *it;
... jadi kita tahu bahwa harus ada beberapa hubungan antara kedua jenis. Untuk iterator non-proxy hubungannya sederhana: reference
selalu value_type
, opsional const dan referensi yang berkualitas. Upaya awal dalam mendefinisikan InputIterator
konsep mensyaratkan bahwa ekspresi *it
dapat dikonversi const value_type &
, dan untuk iterator yang paling menarik sudah cukup.
Saya ingin iterator di C ++ 20 lebih kuat dari ini. Misalnya, perhatikan kebutuhan a zip_iterator
yang mengulangi dua urutan dalam langkah-kunci. Saat dereferensi a zip_iterator
, Anda mendapatkan sementara pair
dari kedua reference
jenis iterator . Jadi, zip
a vector<int>
dan a vector<double>
akan memiliki jenis-jenis terkait ini:
zip
iterator's reference
: pair<int &, double &>
zip
iterator's value_type
:pair<int, double>
Seperti yang Anda lihat, kedua jenis ini tidak saling terkait hanya dengan menambahkan kualifikasi dan level atas cv-. Namun membiarkan kedua jenis itu menjadi sewenang-wenang berbeda terasa salah. Jelas ada beberapa hubungan di sini. Tapi apa hubungannya, dan apa yang dapat diasumsikan oleh algoritma generik yang beroperasi pada iterator dengan aman tentang kedua jenis ini?
Jawaban dalam C ++ 20 adalah bahwa untuk setiap jenis iterator yang valid, proksi atau tidak, tipe reference &&
dan value_type &
berbagi referensi umum . Dengan kata lain, untuk beberapa iterator it
ada beberapa jenis CR
yang membuat berikut ini terbentuk dengan baik:
void foo(CR) // CR is the common reference for iterator I
{}
void algo( I it, iter_value_t<I> val )
{
foo(val); // OK, lvalue to value_type convertible to CR
foo(*it); // OK, reference convertible to CR
}
CR
adalah referensi umum. Semua algoritma dapat mengandalkan fakta bahwa jenis ini ada, dan dapat digunakan std::common_reference
untuk menghitungnya.
Jadi, itulah peran yang common_reference
berperan dalam STL di C ++ 20. Secara umum, kecuali jika Anda menulis algoritma generik atau iterator proxy, Anda dapat mengabaikannya dengan aman. Itu ada di bawah penutup memastikan bahwa iterator Anda memenuhi kewajiban kontrak mereka.
EDIT: OP juga meminta contoh. Ini adalah sedikit dibikin, tapi bayangkan itu C ++ 20 dan Anda diberi berbagai random-access r
jenis R
tentang yang Anda tidak tahu, dan Anda ingin sort
jangkauan.
Lebih jauh bayangkan bahwa untuk beberapa alasan, Anda ingin menggunakan fungsi perbandingan monomorfik std::less<T>
. (Mungkin Anda telah mengetik-menghapus rentang, dan Anda juga perlu mengetik-menghapus fungsi perbandingan dan meneruskannya melalui virtual
? Sekali lagi, peregangan.) Apa yang harus T
di dalam std::less<T>
? Untuk itu Anda akan menggunakan common_reference
, atau helper iter_common_reference_t
yang diimplementasikan dalam hal itu.
using CR = std::iter_common_reference_t<std::ranges::iterator_t<R>>;
std::ranges::sort(r, std::less<CR>{});
Itu dijamin berfungsi, meskipun rentang r
memiliki iterator proxy.
pair<T&,U&>
dan pair<T,U>&
akan memiliki referensi umum, dan itu akan menjadi sederhana pair<T&,U&>
. Namun, untuk std::pair
, tidak ada konversi dari pair<T,U>&
ke pair<T&,U&>
meskipun konversi tersebut pada prinsipnya masuk akal. (Ini, kebetulan, itulah sebabnya kami tidak memiliki zip
pandangan dalam C ++ 20.)
pair
, alih-alih jenis yang dapat secara khusus dirancang untuk tujuannya , dengan konversi implisit yang sesuai sesuai kebutuhan?
std::pair
; jenis pasangan yang cocok dengan konversi yang tepat akan dilakukan, dan range-v3 mendefinisikan jenis pasangan seperti itu. Di Komite, LEWG tidak menyukai gagasan untuk menambahkan ke Perpustakaan Standar jenis yang hampir tetapi tidak cukup std::pair
, baik itu normatif atau tidak, tanpa terlebih dahulu melakukan uji tuntas tentang pro dan kontra dari hanya membuat std::pair
pekerjaan.
tuple
, pair
, tomato
, to
- MAH
- to
. pair
memiliki fitur bagus yang dapat Anda akses elemen dengan .first
dan .second
. Binding terstruktur membantu dengan beberapa kecanggungan bekerja dengan tuple
s, tetapi tidak semua.