不可变的 C++ 容器类 [英] Immutable C++ container class

查看:42
本文介绍了不可变的 C++ 容器类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个 C++ 类 Container,它包含一些 Element 类型的元素.由于各种原因,在施工后对内容进行修改或替换是低效的、不可取的、不必要的、不切实际的和/或不可能的(1).类似于 const std::list (2).

Say that I have a C++ class, Container, that contains some elements of type Element. For various reasons, it is inefficient, undesirable, unnecessary, impractical, and/or impossible (1) to modify or replace the contents after construction. Something along the lines of const std::list<const Element> (2).

Container 可以满足 STL 的容器"和序列"概念的许多要求.它可以提供各种类型,如value_typereference等.它可以提供一个默认构造函数、一个复制构造函数、一个const_iterator类型、begin() constend() constsizeempty,所有的比较运算符,也许还有一些rbegin() constrend() constfront()back()operator[]()at().

Container can meet many requirements of the STL's "container" and "sequence" concepts. It can provide the various types like value_type, reference, etc. It can provide a default constructor, a copy constructor, a const_iterator type, begin() const, end() const, size, empty, all the comparison operators, and maybe some of rbegin() const, rend() const, front(), back(), operator[](), and at().

然而,Container不能提供inserteraseclearpush_frontpush_back、非常量front、非常量back、非常量operator[]、或具有预期语义的非常量 at.所以看起来 Container 不能作为序列".此外,Container 不能提供 operator=swap,也不能提供 iterator 类型指向一个非常量元素.因此,它甚至不能称为容器".

However, Container can't provide insert, erase, clear, push_front, push_back, non-const front, non-const back, non-const operator[], or non-const at with the expected semantics. So it appears that Container can't qualify as a "sequence". Further, Container can't provide operator=, and swap, and it can't provide an iterator type that points to a non-const element. So, it can't even qualify as a "container".

Container 是否遇到了一些功能较弱的 STL 概念?是否有只读容器"或不可变容器"?

Is there some less-capable STL concept that Container meets? Is there a "read-only container" or an "immutable container"?

如果 Container 不符合任何定义的一致性级别,部分一致性是否有价值?当它不符合条件时,使它看起来像一个容器"是否具有误导性?是否有一种简洁、明确的方式可以记录一致性,这样我就不必明确记录一致性语义?同样,一种记录它的方法,以便未来的用户知道他们可以利用只读的通用代码,但不要指望变异算法起作用?

If Container doesn't meet any defined level of conformance, is there value in partial conformance? Is is misleading to make it look like a "container", when it doesn't qualify? Is there a concise, unambiguous way that I can document the conformance so that I don't have to explicitly document the conforming semantics? And similarly, a way to document it so that future users know they can take advantage of read-only generic code, but don't expect mutating algorithms to work?

如果我放宽问题使 Container 是可分配的(但它的元素不是),我会得到什么?此时,operator=swap 是可能的,但是取消引用 iterator 仍然返回一个 const Element.Container 现在是否符合容器"的要求?

What do I get if I relax the problem so Container is Assignable (but its elements are not)? At that point, operator= and swap are possible, but dereferencing iterator still returns a const Element. Does Container now qualify as a "container"?

const std::listContainer 具有大致相同的接口.这是否意味着它既不是容器"也不是序列"?

const std::list<T> has approximately the same interface as Container. Does that mean it is neither a "container" nor a "sequence"?

脚注 (1) 我有涵盖整个范围的用例.我有一个适用于一些只读数据的潜在容器类,因此它必须是不可变的.我有一个潜在的容器,可以根据需要生成自己的内容,因此它是可变的,但您不能按照 STL 要求的方式替换元素.我还有另一个可能的容器,它以一种方式存储它的元素,这种方式会使 insert() 变得如此缓慢,以至于它永远不会有用.最后,我有一个字符串,它以 UTF-8 格式存储文本,同时公开面向代码点的接口;可变实现是可能的,但完全没有必要.

Footnote (1) I have use cases that cover this whole spectrum. I have a would-be-container class that adapts some read-only data, so it has to be immutable. I have a would-be-container that generates its own contents as needed, so it's mutable but you can't replace elements the way the STL requires. I yet have another would-be-container that stores its elements in a way that would make insert() so slow that it would never be useful. And finally, I have a string that stores text in UTF-8 while exposing a code-point oriented interface; a mutable implementation is possible but completely unnecessary.

脚注 (2) 这只是为了说明.我很确定 std::list 需要一个可分配的元素类型.

Footnote (2) This is just for illustration. I'm pretty sure std::list requires an assignable element type.

推荐答案

STL 没有定义任何次要的概念;主要是因为 const 的想法通常在每个迭代器或每个引用级别上表达,而不是在每个类级别上.

The STL doesn't define any lesser concepts; mostly because the idea of const is usually expressed on a per-iterator or per-reference level, not on a per-class level.

你不应该提供具有意外语义的iterator,只提供const_iterator.这允许客户端代码在出错时在最合乎逻辑的位置(带有最易读的错误消息)失败.

You shouldn't provide iterator with unexpected semantics, only provide const_iterator. This allows client code to fail in the most logical place (with the most readable error message) if they make a mistake.

可能最简单的方法是封装它并防止所有非常量别名.

Possibly the easiest way to do it would be to encapsulate it and prevent all non-const aliases.

class example {
    std::list<sometype> stuff;
public:
    void Process(...) { ... }
    const std::list<sometype>& Results() { return stuff; }
};

现在任何客户端代码都确切地知道他们可以对需要变异的 Resultsnada 的返回值做什么.

Now any client code knows exactly what they can do with the return value of Results- nada that requires mutation.

这篇关于不可变的 C++ 容器类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆