Motivasi untuk ekstensi ini, yang dapat dideteksi oleh program yang sesuai, dan dengan demikian tidak sesuai, adalah untuk membuat vector<bool>
berperilaku lebih mirip vector<char>
sehubungan dengan referensi (const dan sebaliknya).
pengantar
Sejak 1998, vector<bool>
telah diejek sebagai "bukan wadah." LWG 96 , salah satu isu POKJA pertama, meluncurkan debat. Hari ini, 17 tahun kemudian, vector<bool>
sebagian besar tetap tidak berubah.
Makalah ini membahas beberapa contoh spesifik tentang bagaimana perilaku vector<bool>
berbeda dari setiap instansiasi lainnya vector
, sehingga merugikan kode generik. Namun makalah yang sama membahas panjang lebar tentang properti kinerja yang sangat bagus vector<bool>
jika diterapkan dengan benar.
Ringkasan : vector<bool>
bukan wadah yang buruk. Ini sebenarnya cukup berguna. Itu hanya memiliki nama yang buruk.
Kembali ke const_reference
Seperti yang diperkenalkan di atas, dan dirinci di sini , yang buruk tentang itu vector<bool>
adalah perilakunya berbeda dalam kode generik daripada vector
contoh lainnya . Berikut adalah contoh konkretnya:
#include <cassert>
#include <vector>
template <class T>
void
test(std::vector<T>& v)
{
using const_ref = typename std::vector<T>::const_reference;
const std::vector<T>& cv = v;
const_ref cr = cv[0];
assert(cr == cv[0]);
v[0] = 1;
assert(true == cv[0]);
assert(cr == cv[0]);
}
int
main()
{
std::vector<char> vc(1);
test(vc);
std::vector<bool> vb(1);
test(vb);
}
Spesifikasi standar mengatakan bahwa assert yang ditandai // Fires!
akan terpicu, tetapi hanya jika test
dijalankan dengan file vector<bool>
. Saat dijalankan dengan vector<char>
(atau vector
selain bool
saat non-default yang sesuai T
ditetapkan), pengujian berhasil.
Implementasi libc ++ berusaha meminimalkan efek negatif karena vector<bool>
berperilaku berbeda dalam kode generik. Satu hal itu untuk mencapai ini adalah untuk membuat vector<T>::const_reference
sebuah proxy referensi , seperti yang ditentukan vector<T>::reference
, kecuali bahwa Anda tidak dapat menetapkan melalui itu. Artinya, di libc ++, vector<T>::const_reference
pada dasarnya adalah penunjuk ke bit di dalam vector
, bukan salinan dari bit itu.
Di libc ++, langkah di atas test
untuk vector<char>
dan vector<bool>
.
Berapa biayanya?
Sisi negatifnya adalah ekstensi ini dapat dideteksi, seperti yang ditunjukkan dalam pertanyaan. Namun, sangat sedikit program yang benar-benar peduli dengan jenis alias ini secara tepat, dan lebih banyak program yang peduli dengan perilakunya.
Apa motivasi untuk ketidaksesuaian ini?
Untuk memberikan klien libc ++ perilaku yang lebih baik dalam kode generik, dan mungkin setelah pengujian lapangan yang memadai, usulkan ekstensi ini ke standar C ++ mendatang untuk kemajuan seluruh industri C ++.
Proposal semacam itu mungkin datang dalam bentuk wadah baru (misalnya bit_vector
) yang memiliki API yang hampir sama seperti saat ini vector<bool>
, tetapi dengan beberapa peningkatan seperti yang const_reference
dibahas di sini. Diikuti dengan penghentian (dan akhirnya penghapusan) vector<bool>
spesialisasi. bitset
bisa juga menggunakan sedikit peningkatan di departemen ini, misalnya menambah const_reference
, dan satu set iterator.
Artinya, di belakang bitset
adalah vector<bool>
(yang harus diganti namanya menjadi bit_vector
- atau apa pun), sebagaimana array
adanya vector
. Dan analogi tersebut harus benar apakah yang kita bicarakan bool
sebagai value_type
dari vector
dan array
.
Ada beberapa contoh fitur C ++ 11 dan C ++ 14 yang dimulai sebagai ekstensi di libc ++. Beginilah cara standar berkembang. Pengalaman lapangan positif yang ditunjukkan secara aktual membawa pengaruh yang kuat. Orang standar adalah kelompok yang konservatif dalam hal mengubah spesifikasi yang ada (sebagaimana mestinya). Menebak, bahkan saat Anda yakin menebak dengan benar, adalah strategi berisiko untuk mengembangkan standar yang diakui secara internasional.
vector<bool>
pada pijakan yang lebih berkelas?vector_bool<Alloc>
dan anarray_bool<N>
untuk mewakili versi yang dikemas (termasuk iterator proxy akses acak yang mengiterasi semua bit) darivector<bool, Alloc>
danarray<bool, N>
. Namun,bitset<N>
(dan sepupunyaboost::dynamic_bitset<Alloc>
) mewakili abstraksi yang berbeda: yaitu versi yang dikemasstd::set<int>
. Jadi saya ingin memiliki, katakanlah,bit_array<N>
danbit_vector<Alloc>
menjadi penerus franchise bitset, dengan iterator dua arah yang sesuai (iterasi pada 1-bit, bukan pada semua bit). Apa pendapat Anda tentang ini?vector<bool>
pengatur proxy akan membuat wadah akses acak yang sesuai dengan standar. Itu bukanvector<bool>
ide yang bagus. :-) Saya setuju dengan Howard. Itu seharusnya disebut sesuatu yang lain.