【发布时间】:2018-09-23 20:15:59
【问题描述】:
假设我们有一个 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 的目的)
【问题讨论】:
-
您的用例是什么?我认为没有理由用 string_views 做你想做的事?
-
@NoSenseEtAl 我正在修改 boost::beast 以将其与 std::string_view 一起使用,而不是 boost::string_view 尽可能少的更改(参见 basic_parsed_list const_iterator 类:github.com/boostorg/beast/blob/develop/include/boost/beast/http/…)。在 Linux 上这就是全部:github.com/boostorg/beast/pull/1241 而在 Windows 上则需要更多的工作......
-
@Justin 这是
it == s.end()部分,将其更改为it == &*s.end()会触发运行时断言错误,即不应取消引用结束迭代器(对于 begin 和 end-1 之间的其余指针,工作)。
标签: c++ std c++17 string-view