Допустим, у нас есть string_view и еще одно string_view, которое является подмножеством первого string_view:
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
Все сравнения будут работать в Linux с gcc (9 HEAD) и clang (8 HEAD). В Windows Visual c++ (15.7.6) сравнение двух итераторов не разрешено (в режиме отладки вы получаете ошибку утверждения cannot compare incompatible string_view iterators for equality
).
Далее идет сравнение указателей:
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
Поэтому, когда вы пытаетесь исправить это в Visual C++, вы хотите сравнить адреса it == &*s.end()
, но это не удается, поскольку итератор end()
не должен разыменовываться (UB, если я правильно помню), поэтому вы получаете cannot dereference end string_view iterator
.
boost::string_view поддерживает сравнение it == s.end()
, поэтому я удивлен, что реализация std более ограничена (и, следовательно, гораздо менее удобна для кросс-платформенной работы)
Я понимаю, что сравнение итераторов двух разных контейнеров - это UB, но string_view не является контейнером (у него нет базовой памяти), это некоторая форма интеллектуального указателя, поэтому я ожидаю, что язык позволит мне сравнивать такие итераторы, доверяя мне, что представления указывают на другое (или одно и то же) подмножество одного и того же контейнера.
Итак, мой вопрос: как я могу заставить что-то подобное работать только с string_view?
(Это означает, что нет необходимости создавать собственный класс диапазона, который будет содержать два итератора, поскольку это в первую очередь противоречит цели использования std::string_view)
it == s.end()
, где изменение его наit == &*s.end()
вызывает ошибку подтверждения во время выполнения, что конечный итератор не следует разыменовывать (для остальных указателей между begin и end-1, которые будут работать). - person Domen Vrankar   schedule 24.09.2018