C++中的一个类要成为容器的条件是什么?

2022-01-24 00:00:00 containers c++

我是 C++ 编程新手,遇到了 containers 这个术语,例如 vectordequemap

I'm new to C++ programming and came across the term containers with examples such as vector, deque, map, etc.

class 在 C++ 中被称为 container 的最低要求是什么?

What should be the minimum requirements that a class should fulfill to be called a container in C++?

推荐答案

我将从 Range 的概念开始.

I will start with the concept Range.

Range 只有两种方法――开始和结束.它们都返回相同类型的迭代器(注意:有建议允许 end 改为返回 Sentinel).

Range has only two methods -- begin and end. They both return iterators of the same type (note: there are proposals to permit end to return a Sentinel instead).

假定读者可以理解迭代器.

Iterators are presumed to be understood by the reader.

高质量的 Range 还可以暴露空、大小、前、后和运算符 [](尤其是随机访问).

A high quality Range can also expose empty, size, front, back, and operator [] (if random access especially).

对于 for(:) 循环,您可以通过作为原始 C 数组,具有 begin()end() 方法,或者在与您的类型相同的命名空间中具有自由函数,这些函数将您的类型作为一个参数(并返回类似迭代器的东西).在这篇文章中,标准中唯一使用 Ranges 的是 for(:) 循环.有人可能会争辩说,this answer 是 C++ 中 Range 概念的唯一实用定义.

For a for(:) loop, you can qualify as a Range by being a raw C array, having begin() and end() methods, or having free functions in the same namespace as your type that take your type as one argument (and return iterator-like things). As of this post, the only thing in the standard that consumes Ranges is for(:) loops. One could argue that this answer is the only practical definition of the concept Range in C++.

接下来,容器.

Container 是一个 Range 至少包含前向迭代器(输入和输出 Ranges 通常不称为 Containers),它拥有它的元素.顺序容器和关联容器是不同的野兽,两者都在标准中定义.

A Container is a Range of at least forward iterators (input and output Ranges are usually not called Containers) that owns its elements. Sequential and Associative containers are different beasts, and both are defined in the standard.

标准中的容器有一组类型定义――值类型、迭代器、常量迭代器.大多数还有分配器(数组除外).它们是空的,并且大多数都有大小(forward_list 除外).

Containers in the standard have a set of typedefs -- value type, iterator, const iterator. Most also have allocator (except array). They have empty, and most have size (except forward_list).

容器都可以由 2 个输入或转发迭代器构造为兼容的值类型,并从初始化列表中构造.

Containers can all be constructed by 2 input or forward iterators to a compatible value type, and from an initializer list.

顺序容器有 push 和 emplace back(前向列表除外)(有些有 emplace/push front),并在迭代器处插入和 emplace(或后向列表).

Sequential containers have push and emplace back (except forward list) (and some have emplace/push front), and insert and emplace at iterator (or after for forward list).

关联容器有一个键类型.其中许多是成对的容器.存储的数据通常是部分常量(数据的关键"部分,在 set 的情况下是关键或整个字段).他们有插入和就位,有和没有提示――他们管理自己的顺序.它们还有 .find.count 方法.

Associative containers have a key type. Many of them are containers of pairs. The data stored is usually partially const (the "key" part of the data, be it the key or the entire field in the case of sets). They have insert and emplace with and without hints -- they manage their own order. They also have a .find and .count methods.

std 库中目前没有依赖于 Container-ness 的函数.并且有一个积极的提议将 Container-ness 和 Range-ness 形式化为 C++17 中的一个概念.Container的实际技术定义在标准中,以防您需要准确创建实际容器;但是,通常您确实需要一个具有编辑方法和所有权机制的 Range.以我的经验,容器概念主要是为了让标准中的行为更容易指定.

There are currently no functions in the std library that depend on Container-ness. And there is an active proposal to make Container-ness and Range-ness be formalized as a concept in C++17. The actual technical definition of Container is in the standard in case you need to create an actual container exactly; however, usually you really need a Range with a means to edit it and ownership mechanics. The Container concept is, in my experience, mostly there to make specifying behaviour easier in the standard.

在添加了 Ranges-v3 之类的东西后,Range 和 Container 的概念将是实际存在于代码中的东西,并且可能存在完全依赖于这些特性的算法.在此之前,它们只是临时概念.

After something like Ranges-v3 is added, the concepts of Range and Container will be actual things that exist in code, and there may be algorithms that depend on exactly those features. Prior to that, they are ad-hoc concepts more than anything.

相关文章