3

“撤消”popFront操作的标准方法是什么?我意识到这不适用于所有范围,但是对于数组之类的东西,说你有

int[] a = [ 1, 2, 3 ];

你做了a.popFront()这会调整开始指针指向a2你将如何撤消该操作以返回1范围内?我知道,std.container.insertFront但这不是我正在寻找的操作。

我努力了

a = a[1..$];
a = a[-1..$];

但第二行抛出一个RangeError. 此外,数组支持切片,但我正在寻找的方法应该支持非随机访问范围和不支持切片的范围。因此,即使a[-1..$]确实有效,也无法解决我的问题。

4

2 回答 2

4

标准方法是在弹出之前保存范围的副本。弹出是一种破坏性突变,范围可以自由地释放元素,重新平衡底层树,或者以其他方式使前一个元素无效。

因此:

MyRange old = current.save;
current.popFront();
if (current.front == magicValue) {
    current = old;
}
于 2013-05-12T01:09:28.157 回答
3

你不撤消popFront。你甚至不能做arr[-1 .. $]与数组等效的事情。如果你想要旧版本,你必须先保存它。

auto saved = range.save;
range.popFront();
range = saved; // "undo" popFront()

数组也不提供比这更多的功能。要在没有范围 API 的情况下对数组执行相同的操作,您必须执行类似的操作

auto saved = arr;
arr = arr[1 .. $];
arr = saved;

在范围或数组上“撤消”弹出操作的唯一方法是先保存它,然后使用旧版本。range API 或数组均未提供任何其他功能。它们不自己保存状态(因此不知道如何撤消先前的操作),甚至数组切片也不知道它们之前或之后在内存中的数据可能是什么(并试图在之前或之前访问内存)正如您在点击 a 时看到的那样,在数组之后将是非法的RangeError)。

因此,如果您必须担心“撤消”任意数量的元素的弹出,那么您可能不得不做一些事情,例如保持原始范围并跟踪您有多少元素弹出它,以便您可以弹出该数量的元素减去您想要的“撤消”级别数。虽然这里可能不会进行太多复制(对于数组,它只是指向同一内存但在其中不同位置的多个切片),如果您不处理切片范围,所有这些弹出可能会很昂贵(就像在弹出每个元素之前保存范围的保存版本一样),特别是如果您试图一次撤消一个级别,因此范围 API 可能不太适合您'正在尝试做,

于 2013-05-12T05:48:41.587 回答