假设我们有一个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),所以您得到{ {1}}。
boost :: string_view支持cannot dereference end string_view iterator
比较,因此令我感到惊讶的是,std实现的局限性更大(因此对跨平台工作的用户友好性更低)
我知道两个不同容器的迭代器比较是UB,但string_view不是容器(它不拥有底层内存),它是某种形式的智能指针,因此我希望该语言允许我比较此类迭代器信任我认为这些视图指向同一容器的不同(或相同)子集。
所以我的问题是如何仅使用string_view进行类似的工作?
(这意味着无需创建将包含两个迭代器的自定义范围类,因为这将首先破坏使用std :: string_view的目的)
答案 0 :(得分:4)
您似乎想使用原始指针。
如果要使用原始指针,请使用q
代替.data()
,并使用.begin()
代替.data()+.size()
。
这些指针的行为就像您希望字符串视图迭代器的行为一样。
如果您需要返回迭代器,则end()
会重建一个迭代器(并将ptr-.data()+.begin()
往返返回ptr)。