Di C ++ 14, wadah asosiatif tampaknya telah berubah dari C ++ 11 - [asosiatif.reqmts] / 13 mengatakan:
Template fungsi anggota
find
,count
,lower_bound
,upper_bound
, danequal_range
akan tidak berpartisipasi dalam resolusi yang berlebihan kecuali jenisCompare::is_transparent
ada.
Apa tujuan membuat komparator "transparan"?
C ++ 14 juga menyediakan template perpustakaan seperti ini:
template <class T = void> struct less {
constexpr bool operator()(const T& x, const T& y) const;
typedef T first_argument_type;
typedef T second_argument_type;
typedef bool result_type;
};
template <> struct less<void> {
template <class T, class U> auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) < std::forward<U>(u));
typedef *unspecified* is_transparent;
};
Jadi misalnya, tidakstd::set<T, std::less<T>>
akan memiliki komparator transparan, tetapi akan memilikinya.std::set<T, std::less<>>
Masalah apa yang dipecahkan ini, dan apakah ini mengubah cara kerja wadah standar? Sebagai contoh, parameter template std::set
masih Key, Compare = std::less<Key>, ...
, jadi tidak default set kehilangan nya find
, count
, dll anggota?
Jawaban:
Lihat jawaban Dietmar dan jawaban remyabel .
Tidak, tidak secara default.
Kelebihan template fungsi anggota baru
find
dll. Memungkinkan Anda menggunakan jenis yang sebanding dengan kunci penampung, alih-alih menggunakan jenis kunci itu sendiri. Lihat N3465 oleh Joaquín Mª López Muñoz untuk alasan dan detail, proposal yang ditulis dengan cermat untuk menambahkan fitur ini.Pada pertemuan Bristol, POKJA setuju bahwa fitur pencarian heterogen berguna dan diinginkan, tetapi kami tidak dapat memastikan bahwa proposal Joaquín akan aman di semua kasus. Proposal N3465 akan menyebabkan masalah serius untuk beberapa program (lihat bagian Dampak pada kode yang ada ). Joaquín menyiapkan draf proposal yang diperbarui dengan beberapa implementasi alternatif dengan trade-off yang berbeda, yang sangat berguna membantu POKJA memahami pro dan kontra, tetapi mereka semua berisiko melanggar beberapa program dengan cara tertentu sehingga tidak ada konsensus untuk menambahkan fitur tersebut. Kami memutuskan bahwa meskipun tidak aman menambahkan fitur tanpa syarat, akan aman jika dinonaktifkan secara default dan hanya "ikut serta".
Perbedaan utama dari proposal N3657 (yang merupakan revisi menit-menit terakhir oleh saya sendiri dan STL berdasarkan N3465 dan draf yang kemudian tidak diterbitkan oleh Joaquín) adalah menambahkan
is_transparent
jenis sebagai protokol yang dapat digunakan untuk ikut serta ke fungsi baru.Jika Anda tidak menggunakan "transparent functor" (yaitu yang mendefinisikan sebuah
is_transparent
tipe) maka kontainer akan berperilaku sama seperti yang biasa mereka lakukan, dan itu masih default.Jika Anda memilih untuk menggunakan
std::less<>
(yang baru untuk C ++ 14) atau jenis "functor transparan" lainnya maka Anda mendapatkan fungsionalitas baru.Penggunaannya
std::less<>
mudah dengan templat alias:Namanya
is_transparent
berasal dari STL's N3421 yang menambahkan "operator berlian" ke C ++ 14. Sebuah "functor transparan" adalah salah satu yang menerima semua jenis argumen (yang tidak harus sama) dan hanya meneruskan argumen tersebut ke operator lain. Functor seperti itu kebetulan persis seperti yang Anda inginkan untuk pencarian heterogen dalam wadah asosiatif, sehingga jenisnyais_transparent
ditambahkan ke semua operator berlian dan digunakan sebagai jenis tag untuk menunjukkan fungsionalitas baru yang harus diaktifkan dalam wadah asosiatif. Secara teknis, kontainer tidak memerlukan "fungsi transparan", hanya satu yang mendukung pemanggilan dengan tipe heterogen (mis.pointer_comp
Tipe di https://stackoverflow.com/a/18940595/981959 tidak transparan menurut definisi STL,pointer_comp::is_transparent
memungkinkannya digunakan untuk memecahkan masalah). Jika Anda hanya pernah lookup di Andastd::set<T, C>
dengan tombol jenisT
atauint
kemudianC
hanya perlu callable dengan argumen tipeT
danint
(dalam rangka baik), tidak perlu untuk benar-benar transparan. Kami menggunakan nama itu sebagian karena kami tidak dapat menemukan nama yang lebih baik (saya lebih sukais_polymorphic
karena fungsi tersebut menggunakan polimorfisme statis, tetapi sudah adastd::is_polymorphic
sifat tipe yang mengacu pada polimorfisme dinamis).sumber
<>
pada proposal tertaut, tetapi proposal itu tidak memperkenalkan<>
- ini adalah sintaks yang ada untuk daftar parameter template kosong. "Fungsi operator berlian" akan sedikit membingungkan.Dalam C ++ 11 tidak ada anggota template
find()
,lower_bound()
dll Artinya, tidak ada yang hilang oleh perubahan ini. Template anggota diperkenalkan dengan n3657 untuk memungkinkan kunci heterogen digunakan dengan wadah asosiatif. Saya tidak melihat contoh konkret di mana ini berguna kecuali untuk contoh yang baik dan buruk!The
is_transparent
Penggunaan ini dimaksudkan untuk menghindari konversi yang tidak diinginkan. Jika templat anggota tidak dibatasi, kode yang ada dapat melewati objek secara langsung yang akan dikonversi tanpa templat anggota. Contoh use-case dari n3657 adalah mencari sebuah objek dalamstd::set<std::string>
menggunakan string literal: dengan definisi C ++ 11, sebuahstd::string
objek dibangun saat meneruskan literal string ke fungsi anggota yang sesuai. Dengan perubahan itu dimungkinkan untuk menggunakan string literal secara langsung. Jika objek fungsi perbandingan yang mendasari diimplementasikan secara eksklusif dalam halstd::string
itu adalah buruk karena sekarang astd::string
akan dibuat untuk setiap perbandingan. Di sisi lain, jika objek fungsi perbandingan yang mendasari dapat mengambilstd::string
dan string literal, yang mungkin menghindari konstruksi objek sementara.is_transparent
Tipe bertingkat dalam objek fungsi perbandingan menyediakan cara untuk menentukan apakah fungsi anggota templated harus digunakan: jika objek fungsi perbandingan dapat menangani argumen heterogen, ia mendefinisikan tipe ini untuk menunjukkan bahwa ia dapat menangani argumen yang berbeda secara efisien. Misalnya, objek fungsi operator baru hanya mendelegasikanoperator<()
dan mengklaim transparan. Itu, setidaknya, bekerjastd::string
yang kelebihan beban lebih sedikit daripada yangchar const*
dianggap oleh operator sebagai argumen. Karena objek fungsi ini juga baru, meskipun mereka melakukan hal yang salah (yaitu memerlukan konversi untuk beberapa jenis), setidaknya, itu bukan perubahan diam yang mengakibatkan penurunan performa.sumber
is_transparent
didefinisikan dalam objek fungsi perbandingan menurut 23.2.4 [asosiatif.reqmts] paragraf 13. Objek fungsi perbandingan default adalahstd::less<Key>
sesuai dengan 23.4.2 [asosiatif.map.syn] dan 23.4. 3 [asosiatif.set.syn]. Menurut 20.10.5 [perbandingan] ayat 4 template umum untukstd::less<...>
tidak tidak menentukan jenis bersarangis_transparent
tetapistd::less<void>
spesialisasi tidak. Artinya, tidak, Anda tidak mendapatkan operator transparan secara default.is_transparent
?Berikut ini adalah semua copy-pasta dari n3657 .
Mengutip Yakk ,
dan n3657,
n3421 memberikan contoh "Fungsi Operator Transparan" .
The kode lengkap di sini .
sumber
std::set<std::string>
benar-benar mendapat manfaat dari "passing thechar const *
through", atau apakah Anda perlu membuatnyastd::set<std::string, std::less<>>
?With the change proposed by N3465 the std::set::find() function would be an unconstrained template which would pass the const char* through to the comparator function, std::less<std::string>, which would construct a std::string temporary for every comparison. The LWG considered this performance problem to be a serious issue.
Stephan T Lavavej berbicara tentang masalah di mana compiler terus membuat temporaries, dan bagaimana proposalnya tentang fungsi operator transparan akan menyelesaikannya di c ++ 1y
GoingNative 2013 - Dont help the Compiler (sekitar tanda jam)
sumber