简体   繁体   中英

Comparing a std::string_view and a substring string_view

Let's say that we have a string_view and another string_view that is a subset of the first 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

All the comparisons would work on Linux under gcc (9 HEAD) and clang (8 HEAD). Under Windows Visual c++ (15.7.6) the comparison of two iterators is not allowed (in debug mode you get an assert error cannot compare incompatible string_view iterators for equality ).

Next is pointer comparison:

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

So when you try to fix it in Visual C++ you want to compare addresses it == &*s.end() but this fails as end() iterator is not supposed to be dereferenced (UB if I remember correctly) so you get cannot dereference end string_view iterator .

boost::string_view supports it == s.end() comparison so I'm surprised that the std implementation is more limiting (and thereby far less user friendly for cross platform work)

I understand that iterator comparison of two different containers is UB but string_view is not a container (it doesn't own underlying memory) it's some form of a smart pointer so I would expect the language to allow me to compare such iterators trusting me that the views are pointing to a different (or same) subset of the same container.

So my question is how can I make something like this work with string_view only?

(Meaning without needing to create a custom range class that will contain two iterators as this would defeat the purpose of using std::string_view in the first place)

You appear to want to work with raw pointers.

If you want to work with raw pointers, use .data() instead of .begin() and .data()+.size() instead of end() .

These pointers behave like you want string view iterators to behave.

If you need iterators back, ptr-.data()+.begin() reconstructs an iterator (and it-begin()+.data() round trips back to ptr).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM