Membandingkan std::string_view dan substring string_view

Katakanlah kita memiliki string_view dan string_view lain yang merupakan subset dari string_view pertama:

using namespace std; // just to shorten the example...

string_view s{"abc def"};
auto t = s.substr(4);
auto u = s.substr(0, 4);

cout << *(s.begin() + 4) << "  " << *t.begin() << '\n';
cout << ((s.begin() + 4) == t.begin());
cout << (s.end() == t.end());
cout << ((s.begin() +5) == t.begin());
cout << ((s.begin() +5) == (t.begin() + 1));
cout << ((s.begin() + 4) == u.end()); // true

Semua perbandingan akan berfungsi di Linux pada gcc (9 HEAD) dan clang (8 HEAD). Di bawah Windows Visual c++ (15.7.6) perbandingan dua iterator tidak diperbolehkan (dalam mode debug Anda mendapatkan kesalahan penegasan cannot compare incompatible string_view iterators for equality).

Berikutnya adalah perbandingan pointer:

string_view s{"abc def"};
char const*& it{...}; // contains pointer to some location in s
auto t = s.substr(4);

it == s.end(); // works in gcc/clang - fails to compile in Visual studio

Jadi ketika Anda mencoba memperbaikinya di Visual C++ Anda ingin membandingkan alamat it == &*s.end() tetapi ini gagal karena end() iterator tidak seharusnya didereferensi (UB jika saya ingat dengan benar) sehingga Anda mendapatkan cannot dereference end string_view iterator.

boost::string_view mendukung perbandingan it == s.end() jadi saya terkejut bahwa implementasi std lebih membatasi (dan karenanya kurang ramah pengguna untuk pekerjaan lintas platform)

Saya memahami bahwa perbandingan iterator dari dua wadah berbeda adalah UB tetapi string_view bukan wadah (tidak memiliki memori yang mendasarinya) ini adalah semacam penunjuk cerdas jadi saya berharap bahasanya memungkinkan saya membandingkan iterator yang memercayai saya bahwa tampilan menunjuk ke subset yang berbeda (atau sama) dari wadah yang sama.

Jadi pertanyaan saya adalah bagaimana saya bisa membuat sesuatu seperti ini berfungsi hanya dengan string_view?

(Artinya tanpa perlu membuat kelas rentang khusus yang akan berisi dua iterator karena ini akan menggagalkan tujuan penggunaan std::string_view sejak awal)


person Domen Vrankar    schedule 23.09.2018    source sumber
comment
Apa kasus penggunaan Anda? Saya tidak melihat alasan untuk melakukan apa yang ingin Anda lakukan dengan string_views?   -  person NoSenseEtAl    schedule 23.09.2018
comment
@NoSenseEtAl Saya memodifikasi boost::beast untuk menggunakannya dengan std::string_view alih-alih boost::string_view dengan perubahan sesedikit mungkin (lihat kelas basic_parsed_list const_iterator: github.com/boostorg/beast/blob/develop/include/boost/beast/http/). Di Linux, hanya ini yang diperlukan: github.com/boostorg/beast/pull/1241 dan di Windows ini sedikit lebih banyak pekerjaan...   -  person Domen Vrankar    schedule 24.09.2018
comment
@Justin itulah bagian it == s.end() di mana mengubahnya menjadi it == &*s.end() memicu kesalahan penegasan runtime bahwa iterator akhir tidak boleh direferensikan (untuk petunjuk lainnya antara awal dan akhir-1 yang akan berfungsi).   -  person Domen Vrankar    schedule 24.09.2018


Jawaban (1)


Anda tampaknya ingin bekerja dengan petunjuk mentah.

Jika Anda ingin bekerja dengan pointer mentah, gunakan .data() sebagai ganti .begin() dan .data()+.size() sebagai ganti end().

Petunjuk ini berperilaku seperti Anda ingin iterator tampilan string berperilaku.

Jika Anda memerlukan iterator kembali, ptr-.data()+.begin() merekonstruksi iterator (dan it-begin()+.data() melakukan perjalanan kembali ke ptr).

person Yakk - Adam Nevraumont    schedule 24.09.2018