比较 std::string_view 和子字符串 string_view
Comparing a std::string_view and a substring string_view
假设我们有一个 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)所以你得到 cannot dereference end string_view iterator
.
boost::string_view 支持 it == s.end()
比较,所以我很惊讶 std 实现的限制更多(因此对跨平台工作的用户友好性要差得多)
我知道两个不同容器的迭代器比较是 UB 但 string_view 不是容器(它不拥有底层内存)它是某种形式的智能指针所以我希望语言允许我比较这样的迭代器相信我这些视图指向同一容器的不同(或相同)子集。
所以我的问题是我怎样才能让这样的东西只与 string_view 一起工作?
(意思是不需要创建包含两个迭代器的自定义范围 class,因为这首先会破坏使用 std::string_view 的目的)
您似乎想使用原始指针。
如果您想使用原始指针,请使用 .data()
而不是 .begin()
和 .data()+.size()
而不是 end()
。
这些指针的行为就像您希望字符串视图迭代器的行为一样。
如果你需要返回迭代器,ptr-.data()+.begin()
重建一个迭代器(并且 it-begin()+.data()
往返返回 ptr)。
假设我们有一个 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)所以你得到 cannot dereference end string_view iterator
.
boost::string_view 支持 it == s.end()
比较,所以我很惊讶 std 实现的限制更多(因此对跨平台工作的用户友好性要差得多)
我知道两个不同容器的迭代器比较是 UB 但 string_view 不是容器(它不拥有底层内存)它是某种形式的智能指针所以我希望语言允许我比较这样的迭代器相信我这些视图指向同一容器的不同(或相同)子集。
所以我的问题是我怎样才能让这样的东西只与 string_view 一起工作?
(意思是不需要创建包含两个迭代器的自定义范围 class,因为这首先会破坏使用 std::string_view 的目的)
您似乎想使用原始指针。
如果您想使用原始指针,请使用 .data()
而不是 .begin()
和 .data()+.size()
而不是 end()
。
这些指针的行为就像您希望字符串视图迭代器的行为一样。
如果你需要返回迭代器,ptr-.data()+.begin()
重建一个迭代器(并且 it-begin()+.data()
往返返回 ptr)。