Saya punya kode seperti ini:
#include <vector>
#include <utility>
int main()
{
std::vector<bool> vb{true, false};
std::swap(vb[0], vb[1]);
}
Argumen tentang kewarasan vector<bool>
samping, ini bekerja dengan baik pada:
- Dentang untuk Mac
- Visual Studio untuk Windows
- GCC untuk Linux
Kemudian saya mencoba membangunnya dengan Dentang pada Windows dan menerima kesalahan berikut (diringkas):
error: no matching function for call to 'swap'
std::swap(vb[0], vb[1]);
^~~~~~~~~
note: candidate function [with _Ty = std::_Vb_reference<std::_Wrap_alloc<std::allocator<unsigned int> > >, $1 = void] not viable: expects an l-value for 1st argument
inline void swap(_Ty& _Left, _Ty& _Right) _NOEXCEPT_COND(is_nothrow_move_constructible_v<_Ty>&&
Saya terkejut bahwa hasilnya berbeda di seluruh implementasi.
Mengapa tidak bekerja dengan Dentang di Windows?
operator[]
nilai yang lebih rendah? dan dapatstd::swap
beroperasi pada nilai dan nilai?/permissive-
(konformitas), yang umumnya harus tetap digunakan;)Jawaban:
Standar tidak mengharuskan ini untuk dikompilasi di rantai alat apa pun !
Ingat pertama yang
vector<bool>
aneh dan berlangganan itu memberi Anda objek sementara dari jenis proxy yang disebutstd::vector<bool>::reference
, bukan yang sebenarnyabool&
.Pesan kesalahan memberitahu Anda bahwa itu tidak dapat mengikat ini sementara untuk
const
referensi non- nilai dalamtemplate <typename T> std::swap(T& lhs, T& rhs)
implementasi generik .Ekstensi!
Namun, ternyata libstdc ++ mendefinisikan overload untuk
std::swap(std::vector<bool>::reference, std::vector<bool>::reference)
, tetapi ini merupakan perluasan ke standar (atau, jika ada di sana, saya tidak dapat menemukan bukti untuk itu).libc ++ juga melakukan ini .
Saya kira implementasi Visual Studio stdlib, yang masih Anda gunakan, tidak , tapi kemudian untuk menambah penghinaan Anda dapat mengikat temporaries ke nilai referensi di VS (kecuali jika Anda menggunakan mode kesesuaian), jadi
std::swap
fungsi standar, "generik", berfungsi sampai Anda mengganti kompiler VS untuk kompiler Dentang yang lebih ketat.Akibatnya, Anda telah mengandalkan ekstensi pada ketiga rantai alat yang berfungsi untuk Anda, dan kombinasi Dentang Windows adalah satu-satunya yang benar-benar menunjukkan kepatuhan yang ketat.
(Menurut pendapat saya, ketiga alat itu seharusnya mendiagnosis hal ini sehingga Anda tidak mengirimkan kode non-portabel selama ini. 😊)
Apa sekarang?
Mungkin tergoda untuk menambahkan spesialisasi Anda sendiri
std::swap
danstd::vector<bool>::reference
, tetapi Anda tidak diizinkan melakukan ini untuk tipe standar; memang, itu akan bertentangan dengan kelebihan yang libstdc ++ dan libc ++ telah memilih untuk ditambahkan sebagai ekstensi.Jadi, agar portabel dan sesuai, Anda harus mengubah kode Anda .
Mungkin yang kuno:
Atau manfaatkan fungsi anggota statis khusus yang melakukan persis seperti yang Anda inginkan :
Dapat juga dieja sebagai berikut:
sumber
std::vector<bool>::reference
sehingga tidak ada yang benar-benar buruk. Bagi saya kedengarannya seperti menggunakan sesuatu sepertichar * foo = "bar";
akan membutuhkan diagnostik karena itu tidak terbentuk.