为什么要使用string_view而不是通用的container_view<T>?

16
我发现新的C++17标准中的string_view有点冗余。
我们已经有了一系列简单机制将数据传递给被调用者,而且没有太多的开销,现在又出现了另一个仅适用于一种容器类型的机制。
我不明白为什么只为字符串提供这种机制,而不是为其他容器提供更普遍的类型。一个合理的答案是我们已经有了这些解决方案。例如,在C++17及以后演示中,string_view被解释为observer_ptr<T> (或 T*) for string
请说明与C++17引入的string_view相比,更一般的container_view的论据。

4
我认为对observer_ptr进行比较只会让问题更加混乱,转移了我们对于是否应该有一个通用的container_view而不是特定的string_view的关注。请注意,翻译时需要保留原文意思并尽量使其易懂,不要添加解释或其他额外内容。 - juanchopanza
2
因为在字符串上操作是最常见的编程任务,我认为答案很明显。 - Jesse Good
container_view 在单个 const char* 上无法工作,但 string_view 有一个额外的假设,即这样的指针指向一个字符串,当它使用该单指针构造函数构造时以 \0 结尾。 - Johannes Schaub - litb
有std::span,它在某种程度上相当于string_view。string / string_view具有特殊操作,这些操作使它们存在的理由超越了普通的容器/视图。Ranges拥有强大的视图功能。 - gast128
2个回答

15
一般化的 `container_view` 更准确地称为 range。我们有一个完全致力于 range 概念的 TS。
现在,我们将 `string_view` 作为单独的类型,因为它具有专门针对字符串的接口,以匹配 `basic_string` 的字符串特定接口。或者至少是匹配 const / 非分配接口。
请注意, `container_view` 或任何你称呼它的东西都无法删除与生成它的容器的连接。或者至少不会在每个访问/操作时支付类型抹消开销。
相比之下, `string_view` 基于 `const char*` 和整数。该类不关心字符串来自哪里;它提供了一个查看连续字符数组的视图,无论谁拥有它。它可以这样做是因为它知道源是一个连续的数组,因此使用指针作为其迭代器的核心。
您无法为任意容器做到这一点。您的 `container_view` 将与 `container_view` 或其他容器视图具有不同的迭代器。它必须如此。这意味着如果您将 `container_view` 作为函数参数,则必须选择要使用的特定容器(强制用户提供恰好该容器类型),使您的函数成为模板,或使用类型抹消迭代器范围(因此速度较慢)。
还有针对 GSL 类型 `span` 和 `mdspan` 的 C++17 后提案。前者表示可修改的连续数组“视图”。后者表示将连续数组视为多维的可修改“视图”。

5

string_view 提供的不仅仅是字符串上简单的指针。 需要将它看作不只是一个简单的非拥有指针:如果只是这样,string_view 就无法让您“切片”字符串的一部分,并对其应用操作(同时仍然是视图;因此不会产生复制的成本):

char *s = "welcome to stackoverflow";
auto s = std::string_view{s + 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

有什么阻止我们为其他容器提供“视图”相同行为的东西吗? - LookAheadAtYourTypes
1
不完全是这样。例如,Boost 就有 array_view(以及 boost.fusion 另一种类型的视图用于过滤、映射等)。唯一的问题是需要手动完成,因为正如我在这里演示的那样,每个容器都需要特定的行为。 - Ven
1
@tomekpe 还有几个竞争性的提案,旨在将通用范围视图(甚至包括称为“span”的可变范围视图,就像Microsoft GSL中提供的那样)纳入标准中。这些提案可能需要达成设计协议,然后才能开始实施。 - Morwenn
1
应该有两个不同的s,我确定。 - Tomilov Anatoliy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接