如何使用foreach语句使Range工作

时间:2012-07-22 20:01:47

标签: foreach range d

我有以下范围:

struct Range {
  uint data;

  @property{
    bool empty() { return false; }
    uint front() { return data; }
    void popFront() { data = data * 2 + 1; }
  }
}

尝试使用它, foreach(c; Rnage()){ /*...*/ }有效,但foreach(i, c; Range()){ /*...*/ }我得到了:

Error: cannot infer argument types

我需要像i这样的foreach(i, v; [1,2,3,4]){ }

2 个答案:

答案 0 :(得分:8)

范围不支持语法

foreach(i, c; range)

虽然看起来很明显这应该适用于简单的情况,但该指数甚至应该取决于范围的类型,并不总是有意义。因此,foreach不会自动提供索引的计数器,并且范围无法提供一个。

但是,感谢tuple unpacking with foreach,您可以使用std.range.sequence std.range.zip和您的范围来实现:

foreach (i, e; zip(sequence!"n"(), range))
{
}

顺便说一句,您不应该使用popFront标记@property。它没有任何意义。 popFront不接受任何参数并且不返回任何值。它根本不像一个变量。而属性的关键是具有像变量一样的函数。如果{当-property的实现被完全整理出来并且它变成了正常的行为(此时它有点错误,这是为什么它暂时是一个单独的开关的一部分),popFront不会可以按照你的定义使用。

答案 1 :(得分:2)

如果使用opApply来实现范围,则可以为without-index样式和with-index样式重载一个版本:

struct Range {
    int opApply(int delegate(int) action){
        uint data=0;
        while(true){
            action(data);
            data=data*2+1;
        }
        return 0;
    }

    int opApply(int delegate(uint,int) action){
        uint i=0;
        foreach(element;this){
            action(i++,element);
        }
        return 0;
    }
}