Скажем, у нас есть 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 - это не контейнер (он не владеет базовой памятью), это некая форма умного указателя, поэтому я ожидаю, что язык позволит мне сравнивать таких итераторов, доверяя мне, что представления указывают на другое (илито же самое) подмножество одного контейнератолько w?
(То есть без необходимости создавать пользовательский класс диапазона, который будет содержать два итератора, так как это лишило бы смысла использование std :: string_view в первую очередь)