为啥使用 string_view 而不是广义的 container_view<T>?
Posted
技术标签:
【中文标题】为啥使用 string_view 而不是广义的 container_view<T>?【英文标题】:Why string_view instead of generalized container_view<T>?为什么使用 string_view 而不是广义的 container_view<T>? 【发布时间】:2016-08-19 08:25:49 【问题描述】:我发现新 C++17 标准中的 string_view 有点多余。
我们为passing data to callee 收集了一组非常详细的简单机制,没有太多开销,现在还有一个也只针对一种容器类型。
我不明白为什么只为字符串提供这种机制,而不是为其他容器提供更通用的类型。一个明智的答案是我们已经有了这些解决方案。例如,在C++17 and beyond 演示文稿中,string_view 被解释为observer_ptr<T> (or T*) for string
。
请针对更通用的 container_view 陈述论点,与 C++17 引入的 string_view 形成对比。
【问题讨论】:
我认为observer_ptr
的比较只会造成混淆,并削弱是否应该有一个通用的container_view
而不是具体的string_view
的问题。
因为对字符串的操作是最常见的编程任务?我认为答案很简单。
container_view 不能在单个const char*
上工作,但string_view
有一个额外的假设,即这样的指针指向一个字符串,以\0
终止当它用那个单指针构造函数构造时。
【参考方案1】:
广义的container_view
更恰当地称为范围。我们有一个 TS en-route 完全致力于范围概念。
现在,我们将string_view
作为一个单独的类型,因为它有一个专门的、特定于字符串的接口来匹配basic_string
的特定于字符串的接口。或者至少,匹配 const/非分配接口。
请注意,container_view
或您所称的任何名称都无法删除它与生成它的容器的连接。或者至少,在每次访问/操作上都需要支付类型擦除开销。
相比之下,string_view
基于const char*
s 和整数。该类不关心字符串来自何处;无论谁拥有它,它都可以查看连续的字符数组。它可以这样做是因为它知道源是一个连续的数组,因此使用指针作为其迭代器的核心。
您不能对任意容器执行此操作。您的 container_view<vector>
将具有与 container_view<list>
或其他不同的迭代器。 必须。这意味着,如果您将 container_view
作为函数参数,则必须选择要使用的特定容器(强制用户准确提供该容器类型),将函数设为模板,或使用类型擦除的迭代器范围(因此速度较慢)。
还有针对 GSL 类型 span
和 mdspan
的后 C++17 提案。前者表示 连续 数组的可修改“视图”。后者表示您视为多维的连续数组的可修改“视图”。
【讨论】:
【参考方案2】:string_view
提供的不仅仅是一个简单的字符串指针。
您需要将其视为不仅仅是一个简单的非拥有指针:如果仅此而已,string_view
不允许您“切片”字符串的一部分,并对它应用操作(同时仍然是一个视图;因此不会产生复制成本):
char *s = "welcome to ***";
auto s = std::string_views + 8, 2; // a view on "to"
// you can then apply many operations on this view, that wouldn't make sense more on your general non_owning<T>:
s.remove_prefix(std::min(s.find_first_not_of(" "), s.size()));
// it also "inherits" (copies the API) a lot directly from std::basic_string
auto view2 = s.substr(3, 4); // a generic non-owning ptr would copy here, instead of giving you a new view
【讨论】:
有什么东西阻止我们为其他容器提供相同的“视图”行为吗? 并非如此。这就是为什么Boost,例如,有array_view
(和boost.fusion另一种类型的过滤器、地图等视图)。唯一的问题是您需要手动完成,因为正如我在这里演示的那样,您需要每个容器的特定行为。
@tomekpe 还有几个相互竞争的提议将通用范围视图包含在标准中(甚至还有一个可变范围视图,称为“跨度”,就像 Microsoft GSL 中提供的那样)。这些提案可能需要在供应商开始实施之前达成设计协议。
应该有两个不同的s
es,我确定。以上是关于为啥使用 string_view 而不是广义的 container_view<T>?的主要内容,如果未能解决你的问题,请参考以下文章
为啥按值传递 string_view?为啥 Visual Studio 不能对此进行优化?
为啥这个 std::string_view 不是常量表达式?
为啥 std::string_view 比 const char* 快?
为什么将`const char [N]`和`const char *`传递给view :: c_str()会产生不同的二进制文件,而string_view会产生相同的结果吗?
为啥 C++ 标准中没有 std::string_view 类型的参数的 std::basic_string 类的构造函数[重复]