Seperti (semoga) kita semua tahu, vector<bool>
benar-benar rusak dan tidak dapat diperlakukan sebagai array C. Apa cara terbaik untuk mendapatkan fungsi ini? Sejauh ini, ide yang saya pikirkan adalah:
- Gunakan sebagai
vector<char>
gantinya, atau - Gunakan kelas pembungkus dan miliki
vector<bool_wrapper>
Bagaimana kalian menangani masalah ini? Saya membutuhkan c_array()
fungsionalitas tersebut.
Sebagai pertanyaan sampingan, jika saya tidak memerlukan c_array()
metode ini, apa cara terbaik untuk mengatasi masalah ini jika saya memerlukan akses acak? Haruskah saya menggunakan deque atau yang lainnya?
Edit:
- Saya membutuhkan ukuran dinamis.
- Bagi yang belum tahu,
vector<bool>
dikhususkan sehingga masing-masingbool
butuh 1 bit. Dengan demikian, Anda tidak dapat mengubahnya menjadi array gaya C. - Saya kira "wrapper" adalah istilah yang salah. Saya sedang memikirkan sesuatu seperti ini:
Tentu saja, saya harus membaca my_bool
karena kemungkinan masalah penyelarasan :(
struct my_bool
{
bool the_bool;
};
vector<my_bool> haha_i_tricked_you;
vector<bool>
hanya menyebabkan bug data race dalam kode saya, karena saya mengharapkan utas yang berbeda dapat memodifikasi elemen yang berbeda dalam vektor pada saat yang sama dengan aman. Diselesaikan menggunakandeque<bool>
.Jawaban:
Gunakan
std::deque
jika Anda tidak membutuhkan array, ya.Jika tidak, gunakan alternatif
vector
yang tidak mengkhususkanbool
, seperti yang ada di Boost Container .sumber
Itu masalah yang menarik.
Jika Anda memerlukan apa yang akan menjadi std :: vector jika tidak terspesialisasi, maka mungkin sesuatu seperti itu akan bekerja dengan baik dengan kasus Anda:
#include <vector> #include <iostream> #include <algorithm> class Bool { public: Bool(): m_value(){} Bool( bool value ) : m_value(value){} operator bool() const { return m_value; } // the following operators are to allow bool* b = &v[0]; (v is a vector here). bool* operator& () { return &m_value; } const bool* operator& () const { return &m_value; } private: bool m_value; }; int main() { std::vector<Bool> working_solution(10, false); working_solution[5] = true; working_solution[7] = true; for( int i = 0; i < working_solution.size(); ++i ) { std::cout<< "Id " << i << " = " << working_solution[i] << "(" <<(working_solution[i] ? "true" : "false") << ")" <<std::endl; // i used ? : to be sure the boolean evaluation is correct } std::sort( working_solution.begin(), working_solution.end()); std::cout<< "--- SORTED! ---" << std::endl; for( int i = 0; i < working_solution.size(); ++i ) { bool* b = &working_solution[i]; // this works! std::cout<< "Id " << i << " = " << working_solution[i] << "(" << (working_solution[i] ? "true" : "false") << ")" <<std::endl; // i used ? : to be sure the boolean evaluation is correct } std::cin.get(); return 0; }
Saya mencoba ini dengan VC9 dan tampaknya berfungsi dengan baik. Ide dari kelas Bool adalah untuk mensimulasikan tipe bool dengan menyediakan perilaku dan ukuran yang sama (tapi bukan tipe yang sama). Hampir semua pekerjaan dilakukan oleh operator bool dan konstruktor salinan default di sini. Saya menambahkan semacam untuk memastikannya bereaksi seperti yang diasumsikan saat menggunakan algoritma.
Tidak yakin itu akan cocok untuk semua kasus. Jika itu tepat untuk kebutuhan Anda, itu akan lebih mudah daripada menulis ulang kelas seperti vektor ...
sumber
sizeof(bool)
tidak harus ada1
"operator bool() const
ke fileoperator bool&()
. Ini membuatnya mencerminkan perilaku bool sederhana dengan lebih baik karena mendukung penugasan, dll. Dalam kasus sepertiv[0] = true;
saya benar-benar tidak dapat melihat masalah dengan perubahan ini, jadi bolehkah saya mengeditnya?Tergantung kebutuhan Anda. Saya akan memilih keduanya
std::vector<unsigned char>
. Menulis pembungkus bisa baik-baik saja jika Anda hanya menggunakan sebagian dari fungsionalitas, jika tidak maka akan menjadi mimpi buruk.sumber
unsigned char
selalu berupa satu byte sementarauint8_t
mungkin tidak didukung oleh implementasi.uint_fast8_t
bisa bekerja meskipun jika tujuannya adalah untuk membuatnya jelas itu satu byte dan bukan karakter, tapi Anda mungkin juga menggunakanstd::byte
kemudianboost::container::vector<bool>
:sumber
Pertimbangkan untuk menggunakan vektor <int>. Setelah Anda melewati kompilasi dan pengecekan tipe, bool dan int keduanya hanyalah kata-kata mesin (edit: tampaknya ini tidak selalu benar; tetapi akan benar pada banyak arsitektur PC). Dalam kasus di mana Anda ingin mengonversi tanpa peringatan, gunakan "bool foo = !! bar", yang mengonversi nol menjadi salah dan bukan nol menjadi benar.
Sebuah vektor <char> atau yang serupa akan menggunakan lebih sedikit ruang, meskipun itu juga berpotensi untuk menerima kecepatan (sangat kecil) dalam beberapa keadaan, karena karakter lebih kecil dari ukuran kata mesin. Ini, saya yakin, alasan utama bools diimplementasikan menggunakan int, bukan chars.
Jika Anda benar-benar ingin semantik yang bersih, saya juga menyukai saran untuk membuat kelas boolean Anda sendiri - terlihat seperti bool, berfungsi seperti bool, tetapi menipu spesialisasi template.
Juga, selamat datang di klub orang-orang yang menginginkan spesialisasi vektor <bool> diturunkan dari standar C ++ (dengan bit_vector untuk menggantikannya). Itu tempat berkumpulnya anak-anak keren :).
sumber
Masalah ini telah dibahas di comp.lang.c ++. Dimoderasi. Solusi yang diusulkan:
std::allocator
) dan spesialisasi vektor sendiri;std::deque
(seperti yang disarankan di awal dalam salah satu buku S. Mayers) - tetapi ini bukan untuk kebutuhan Anda;bool
pembungkus POD ;char
/int
/ etc) dengan ukuran yang sama sebagaibool
gantinyabool
;Juga awal saya melihat proposal untuk komite standar - memperkenalkan makro (seperti
STD_VECTOR_BOOL_SPECIAL
) untuk melarang spesialisasi ini - tetapi AFAIK proposal ini tidak diimplementasikan dalam implementasi stl dan tidak disetujui.Tampaknya masalah Anda tidak memiliki cara untuk melakukannya dengan baik ... Mungkin di C ++ 0x.
sumber
Jawaban paling sederhana adalah penggunaan
vector<struct sb>
manasb
adalahstruct {boolean b};
. Kemudian Anda bisa mengatakanpush_back({true})
. Sepertinya bagus.sumber
Solusi pilihan saya adalah
vector
enum terbatas yang memiliki jenis yang mendasaribool
. Ini hampir sama dengan yangvector<bool>
akan kami alami jika komite tidak mengkhususkannya.enum class switch_status : bool { ON, OFF }; static_assert( sizeof( switch_status ) == 1 ); ::std::vector<switch_status> switches( 20, switch_status::ON ); static_assert( ::std::is_same_v< decltype( switches.front() ), switch_status &> ); static_assert( ::std::is_same_v< decltype( switches.back() ), switch_status &> ); static_assert( ::std::is_same_v< decltype( switches[ 0 ] ), switch_status &> );
Anda akan memiliki pendapat sendiri tentang kebijaksanaan merangkul pemain ke / dari
bool
:enum class switch_status : bool { OFF = false, ON = true }; static_assert( static_cast< bool >( switch_status::ON ) == true ); static_assert( static_cast< bool >( switch_status::OFF ) == false ); static_assert( static_cast< switch_status >( true ) == switch_status::ON ); static_assert( static_cast< switch_status >( false ) == switch_status::OFF );
sumber