std.exception
このモジュールは例外や、 一般のエラー処理のためのツールを定義しています。 Synopsis:string synopsis() { FILE* f = enforce(fopen("some/file")); // ここから先は f は必ず null でない FILE* g = enforceEx!(WriteException)(fopen("some/other/file", "w")); // ここから先は g は必ず null でない Exception e = collectException(write(g, readln(f))); if (e) { ... 例外が発生した場合 ... } char[] line; enforce(readln(f, line)); return assumeUnique(line); }Source:
std/exception.d License:
Boost License 1.0 Authors:
Andrei Alexandrescu
- If value が非ゼロならそのまま返し、そうでなければ
new Exception(msg) 例外を投げます
Example:
auto f = enforce(fopen("data.txt")); auto line = readln(f); enforce(line.length); // 空行を期待
- value が非ゼロなら、その値を返します。
そうでなければ、例外 ex を投げます。
Example:
auto f = enforce(fopen("data.txt")); auto line = readln(f); enforce(line.length, new IOException); // 空行を期待
- value が非ゼロなら、その値を返します。それ以外の場合、new
ErrnoException(msg) を投げます。ErrnoException クラスは、
最後の動作が errno にエラーコードを設定したことを仮定しています。
Example:
auto f = errnoEnforce(fopen("data.txt")); auto line = readln(f); enforce(line.length); // 空でない行を期待
- value が非ゼロならそのまま返し、そうでなければ
new E(msg) を投げます
Example:
auto f = enforceEx!(FileMissingException)(fopen("data.txt")); auto line = readln(f); enforceEx!(DataCorruptionException)(line.length);
- expression を評価して、その結果例外が発生したらその例外を返します。
それ以外では、式の評価結果を
target に格納し、null を返します。
Example:
int[] a = new int[3]; int b; assert(collectException(a[4], b));
- expression を評価して、その結果例外が発生したらその例外を返します。 それ以外の場合は null を返します。T は void でも構いません。
- 書き換え可能な配列をimmutable配列に書き換えるイディオムです。
実装としては、assumeUnique は単純にキャストを行うだけです。
しかし、この名前を使うことで、arrayへの参照が他に残っていないという仮定をしていることが
ソースから読み取れるようになります。 assumeUnique(arr) は、他に arr
の要素を指すmutable参照が決して残っていない時にのみ呼び出されるべきです。この仮定を強固にするために、
assumeUnique(arr) はreturnする前に引数 arr をnullクリアします。本質的には、assumeUnique(arr) は呼び出し側の
「もう arr の(推移的)要素を書き換える参照は他にない」
「この先の操作は全て
assumeUnique の返すimmutable配列に対して行う」という決意表明と言えます。
良くある例としては、assumeUnique
は関数内でメモリを割り当て中身を構築した配列を返すときに使われます。
Example:
string letters() { char[] result = new char['z' - 'a' + 1]; foreach (i, ref e; result) { e = 'a' + i; } return assumeUnique(result); }
result は letters 関数内のローカル変数で、関数が return した後に書き換わることがないので、 上の例は正しい使い方です。これに対して次の例は、 assumeUnique の間違った使い方です。 Bad:
private char[] buffer; string letters(char first, char last) { if (first >= last) return null; // fine auto sneaky = buffer; sneaky.length = last - first + 1; foreach (i, ref e; sneaky) { e = 'a' + i; } return assumeUnique(sneaky); // BAD }
この例はクライアント側のコードを破滅させてしまいます。 呼び出し側に対しては変更されないと宣言されている配列を書き換えているからです。 書き込み可能な配列 buffer から正しく immutable な配列を得るには、 最後の行をこうします:return to!(string)(sneaky); // 大丈夫
このコードは適切に配列のコピーを作成します。 参照が一つしかないことをコンパイル時に保証するのは、特定の場合では可能です (ArchJava 言語の unique と lent キーワード)が、 言語がかなり複雑になります。 assumeUnique のような慣習に基づいた方法の欠点は、 現時点では仮定の正しさをフォーマルに検証する術がなにもないことです。一方で利点は、 一方で利点は、このような assumeUnique の使い方はシンプルで、まあまあ使う気になれるところです。 - source の表現が target の表現もしくはその内部を指すポインタを含んでいる場合、 true を返します。pointsTo(x, x) とすると、x が自分自身を指すポインタを含んでいるかどうかのチェックとなります。
- errno を設定するエラーが発生したときに投げられる例外