static foreach
タプル章で、コンパイル時のforeach
について説明した。コンパイル時のforeach
は、コンパイル時にループを反復し、各反復を個別のコードとして展開する。例えば、タプルを反復する次のforeach
ループがある。
コンパイラは、ループを次のような同等のコードに展開する:
コンパイル時のforeach
は非常に強力であるが、場合によっては、その一部の特性が適さない場合もある。
- コンパイル時
foreach
では、ループの展開ごとにスコープが追加される。上記のi
とmember
変数のように、これにより、複数のスコープでシンボルを使用しても多重定義エラーが発生しない。これは一部のケースでは望ましいが、1つの反復展開されたコードが他の反復のコードを使用できなくなる。 - コンパイル時の
foreach
は、タプル(AliasSeq
の形式のテンプレート引数を含む)でのみ機能する。例えば、次の配列リテラルの要素はコンパイル時に既知であるにもかかわらず、ループは常に実行時に実行される(これはまさに望ましい動作である場合もある)。
- 通常の
foreach
と同様に、コンパイル時のforeach
は関数内でのみ使用できる。例えば、モジュールスコープやユーザー定義の型定義内では使用できない。
エラー: 宣言が必要、foreach
ではない
- コンパイル時の
foreach
では、ループ本体内のbreak
およびcontinue
文が、コンパイル時のループの反復自体に影響を与えるのか、それとも展開されたコードの一部となるのかが明確ではない場合がある。
static foreach
は、より強力なコンパイル時機能で、より詳細な制御を提供する:
static foreach
は、コンパイル時に計算できるあらゆる範囲の要素(1..10
のような数値範囲を含む)で使用できる。例えば、Rangesの章で説明したFibonacciSeries
の範囲と、数値が偶数であるかどうかを判断する関数がある。
上記のループは、以下の同等のコードに展開される:
static foreach
モジュールスコープで使用できる。static foreach
各反復に個別のスコープを導入しない。例えば、次のループは、モジュールスコープで関数の2つのオーバーロードを定義している。
上記のループは、以下の同等のコードに展開される:
break
また、static foreach
ループ内のcontinue
文は、明確にするためにラベルが必要だ。例えば、次のコードは、switch
文内のcase
句を展開(生成)する。各case
句の下にあるbreak
文は、関連するswitch
文をラベルで指定する必要がある。
上記のループが展開されると、switch
文は次のコードと同等になる。