3

私は次の範囲を持っています:

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]){ }です。

4

2 に答える 2

8

範囲は構文をサポートしていません

foreach(i, c; range)

単純なケースではそれが機能することは明らかですが、そのインデックスがどうあるべきかは範囲のタイプにも依存し、常に意味があるとは限りません。そのため、インデックスのカウンターは foreach によって自動的に提供されず、範囲にはそれを提供する方法がありません。

ただし、 foreach を使用したタプルのアンパックのおかげで、範囲を使用してそれを行うことができます。std.range.sequence std.range.zip

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

ちなみに、 でマークpopFrontしてはいけません@property。意味がありません。popFront引数を取らず、値を返しません。変数のようにはまったく機能しません。プロパティのポイントは、変数のように機能する関数を持つことです。If/when-propertyの実装が完全に整理され、通常の動作になります (現時点ではかなりバグがあり、現時点では別のスイッチである理由の一部です)、popFront定義したとおりに使用できません。

于 2012-07-23T00:03:50.490 に答える
2

範囲を実装するために使用する場合はopApply、インデックスなしのスタイルとインデックスありのスタイルの 1 つのバージョンをオーバーロードできます。

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;
    }
}
于 2012-07-23T01:59:18.420 に答える