Сравнение std :: string_view и подстроки string_view - PullRequest
0 голосов
/ 23 сентября 2018

Скажем, у нас есть 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 в первую очередь)

1 Ответ

0 голосов
/ 24 сентября 2018

Похоже, вы хотите работать с необработанными указателями.

Если вы хотите работать с необработанными указателями, используйте .data() вместо .begin() и .data()+.size() вместо end().

Эти указатели ведут себя так, как вы хотите, чтобы итераторы представления строк работали.

Если вам нужны итераторы назад, ptr-.data()+.begin() восстанавливает итератор (и it-begin()+.data() возврат в обратном направлении к ptr).

...