比较 std::string_view 和子字符串 string_view

Dom*_*kar 0 c++ std string-view c++17

假设我们有一个 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
Run Code Online (Sandbox Code Playgroud)

所有比较都可以在 gcc (9 HEAD) 和 clang (8 HEAD) 下的 Linux 上进行。在 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
Run Code Online (Sandbox Code Playgroud)

因此,当您尝试在 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 的目的)

Yak*_*ont 5

您似乎想要使用原始指针。

如果您想使用原始指针,请使用.data()代替.begin().data()+.size()代替end()

这些指针的行为就像您希望字符串视图迭代器的行为一样。

如果您需要返回迭代器,ptr-.data()+.begin()请重建迭代器(并it-begin()+.data()往返返回 ptr)。