D 一个pushBack()函数,与popFront()相反

D 一个pushBack()函数,与popFront()相反,d,D,我是否可以使用popFront(),然后最终将弹出的内容向后推?调用popFront()的次数可能不止一次(但如果有必要的话,可以说不超过10次)。这也是虚拟的pushBack()函数也将被调用的调用次数 例如: string s = "Hello, World!"; int n = 5; foreach(i; 0 .. n) { // do something with s.front s.popFront(); } if(some_condition) { fore

我是否可以使用
popFront()
,然后最终将弹出的内容向后推?调用
popFront()
的次数可能不止一次(但如果有必要的话,可以说不超过10次)。这也是虚拟的
pushBack()
函数也将被调用的调用次数

例如:

string s = "Hello, World!";
int n = 5;
foreach(i; 0 .. n) {
    // do something with s.front
    s.popFront();
}

if(some_condition) {
    foreach(i; 0 .. n) {
        s.pushBack();
    }
}
writeln(s); // should output "Hello, World!" since number of poped is same as pushed back.
我认为
popFront()
确实使用了
.ptr
,但我不确定它在D中是否有任何区别,是否能帮助我轻松实现目标(即,以D的方式,而不是用a左右的字母写我自己的)


一种完全不同的方法也很受欢迎。

不,没有标准的方法来“取消”范围或字符串

如果要将字符串的一部分传递给函数:

fun(s[5..10]);
您可能希望该函数只能看到这5个字符。如果有一种方法可以“取消映射”切片,那么函数将能够看到整个字符串


现在,D是一种系统编程语言,所以可以使用指针算法和GC查询来扩展切片。但是标准库中没有任何方法可以为您执行此操作。

不,没有标准方法可以“取消映射”范围或字符串

如果要将字符串的一部分传递给函数:

fun(s[5..10]);
您可能希望该函数只能看到这5个字符。如果有一种方法可以“取消映射”切片,那么函数将能够看到整个字符串


现在,D是一种系统编程语言,所以可以使用指针算法和GC查询来扩展切片。但是标准库中没有任何内容可以为您这样做。

范围要么是生成的(例如,如果它是一个随机数列表),要么是容器中的视图。在这两种情况下,把任何东西推到上面都没有意义。在调用
popFront
时,您正在遍历列表并缩小容器视图。如果你认为一个范围就像两个C++迭代器,你有一些类似

的东西。
struct IterRange(T)
{
    @property bool empty() { return iter == end; }
    @property T front() { return *iter; }
    void popFront() { ++iter; }

    private Iterator iter;
    private Iterator end;
}
str = newChar ~ str;
这样就更容易理解了。如果调用了
popFront
,它会将迭代器向前移动一步,从而更改正在查看的元素,但不能在其前面添加元素。这需要在容器本身上执行类似于插入的操作,可能可以使用迭代器或范围来告诉容器要在何处插入alement,但迭代器或范围本身不能这样做。如果你有一个生成范围,比如

struct IncRange(T)
{
    @property bool empty() { value == T.max; }
    @property T front() { return value; }
    void popFront() { ++value; }

    private T value;
}
它不断增加值,并且没有容器支持它。所以,它甚至没有任何地方可以将值推到上面

数组有点滑稽,因为它们是范围,但它们也是容器(某种程度上)。它们在弹出元素或切片元素时具有范围语义,但它们不拥有自己的内存,一旦附加到它们,就可以获得具有相同值的完全不同的内存块。因此,这是一个可以添加和删除元素的范围,但不能使用范围API。所以,你可以这样做

struct IterRange(T)
{
    @property bool empty() { return iter == end; }
    @property T front() { return *iter; }
    void popFront() { ++iter; }

    private Iterator iter;
    private Iterator end;
}
str = newChar ~ str;
但这并不十分有效。您可以通过以目标大小创建一个新数组,然后填充其元素而不是重复连接来提高效率,但无论如何,在数组的前面推送某些内容并不是一件特别惯用或有效的事情

现在,如果你想做的只是重置范围,使其再次引用弹出的元素,而不是真正将元素推到其上-也就是说,再次打开窗口,使其显示之前显示的内容-这有点不同。range API仍然根本不支持它(您永远无法取消弹出的任何内容)。但是,如果要处理的范围是正向范围(数组也是),则可以在弹出元素之前保存该范围,然后使用该范围恢复以前的状态。e、 g

string s = "Hello, World!";
int n = 5;
auto saved = s.save;
foreach(i; 0 .. n)
    s.popFront();

if(some_condition)
    s = saved;

因此,您必须自己显式存储上一个状态才能还原它,而不是像
unposfront
,但是在大多数情况下,拥有该范围存储本身(如
unposfront
)是非常低效的(如果范围跟踪容器的开始位置,则在迭代器情况下可能会起到很大作用)。

范围是生成的(例如,如果它是一个随机数列表)这是一个容器的视图。在任何情况下都不可能把任何东西推到它上面。当你调用<代码> POPONDS时,你正在迭代列表并缩小容器的视图。如果你认为一个范围像两个C++迭代器一段时间,你就有类似于

的东西。
struct IterRange(T)
{
    @property bool empty() { return iter == end; }
    @property T front() { return *iter; }
    void popFront() { ++iter; }

    private Iterator iter;
    private Iterator end;
}
str = newChar ~ str;
这样就更容易理解了。如果调用
popFront
,它会将迭代器向前移动一步,从而更改正在查看的元素,但不能在其前面添加元素。这需要在容器本身上进行类似插入的操作,也许可以使用迭代器或范围来告诉容器,您希望在其中插入一个alement,但迭代器或范围本身不能这样做

struct IncRange(T)
{
    @property bool empty() { value == T.max; }
    @property T front() { return value; }
    void popFront() { ++value; }

    private T value;
}
它不断增加值,并且没有容器支持它,因此,它甚至没有任何可以将值推送到的地方

数组有点滑稽,因为它们是范围,但它们也是容器(有点)。它们在弹出元素或对元素进行切片时具有范围语义,但它们不拥有自己的内存,一旦附加到它们,就可以获得具有相同值的完全不同的内存块。因此,这是一种可以添加和删除元素的范围,但不能使用范围API来执行。因此,可以执行som类似于

struct IterRange(T)
{
    @property bool empty() { return iter == end; }
    @property T front() { return *iter; }
    void popFront() { ++iter; }

    private Iterator iter;
    private Iterator end;
}
str = newChar ~ str;
但这并不十分有效。你可以通过创建一个新的arra来提高效率