0

假设我们有一个 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

所有比较都适用于 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

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

4

1 回答 1

4

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

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

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

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

于 2018-09-24T00:09:18.323 回答