59996


`RedBlackTree`の要素は、次のように`foreach`を使って列挙することができます。

[code]

    auto t = new RedBlackTree!int;
    // ...
    foreach(elem; t) {
      // ...
    } 
    
[/code]

ところで、一般に`foreach`で要素を列挙するためには

  * `opApply`を定義
  * `empty`, `front`, `popFront`を定義

のいずれかが必要だという認識なのですが、[ソースコード](https://github.com/dlang/phobos/blob/v2.088.0/std/container/rbtree.d)を見る限り、`RedBlackTree`は`opApply`も`popFront`も持っていないようです。

`RBRange`は2番目に挙げた3つのメソッドを持っていますが、`foreach`の`;`の右側に(`RBRange`ではなく)`RedBlackTree`を置ける理由が分かりません。

(コンパイラ: DMD 2.088.0)


CC BY-SA 4.0
2019-10-20T04:28:10.940
59820
2019-10-26T14:03:35.917
2019-10-21T12:04:01.520
13199
13199
question
d
foreachを使ってRedBlackTreeの要素を列挙できるのは何故でしょうか


結論から言うと、コンパイラが自動的に(引数を取らず、レンジを返す)`opIndex`または`opSlice`呼び出しに置き換えた上で処理を行ってくれるからでした。

したがって、次のようなコードを書くことができます。

[code]

    //import std.stdio : writeln;
    
    struct R {
        bool empty() {
            return false;
        }
    
        long front() {
            return 11111111;
        }
    
        void popFront() {
        }
    }
    
    class A {
        // opSliceの定義をコメントアウトすると、コンパイルエラー
        auto opSlice() {
            return R();
        }
    }
    
    void main() {
        auto a = new A;
    
        foreach (v; a) {
            //writeln(v);
        }
    }
    
[/code]

言語リファレンス[1](https://dlang.org/spec/statement.html)には、この機能について書かれた部分は見つけられませんでしたが、「The
D Programming Language
(TDPL)」には記述があるそうです[2](https://issues.dlang.org/show_bug.cgi?id=5605)。

以下参考にしたリンクです。

ちょうどRedBlackTreeを例にして説明しています。  
[User defined type and foreach - D Programming Language Discussion
Forum](https://forum.dlang.org/post/mailman.189.1510830561.9493.digitalmars-d-
learn@puremagic.com)

この機能が導入された経緯について言及しています  
[When to opCall instead of opIndex and opSlice? - D Programming Language
Discussion
Forum](https://forum.dlang.org/post/mailman.291.1506972010.3410.digitalmars-d-
learn@puremagic.com)


CC BY-SA 4.0
2019-10-26T14:03:35.917
59996
2019-10-26T14:03:35.917
13199
59820
answer