D の out と inout
まあ滅多に使わんのですが。ちょっとはまったのでメモ。
Phobos の math ライブラリに、以下のような関数がある。
ようは浮動小数のあまりを求める関数なのだが、第2引数の「inout real y」ではまった。
real modf(real x, inout real y)
以下のような感じにしてたのだが、
んでまあ、
BgObj[i].pos[X] = cast(float)modf(cast(real)BgObj[i].pos[X], cast(real)BgObj[i].vel[X]);
ようは「cast(real)BgObj[i].vel[X] は左辺値じゃねえよ!」とコンパイラ様は仰られてる。
bg.d(n): Error: cast(real)( (*(&( (bg_obj)[(i)]) + 16))[0]) is not an lvalue
正解は、
としなきゃならん。つまり「inout」や「out」指定された引数には cast(hoge) は使えないというか、考えたら至極まっとうな話だった、という落ち。
real tmp = cast(real)BgObj[i].vel[X];
BgObj[i].pos[X] = cast(float)modf(cast(real)BgObj[i].pos[X], tmp);
ドキュメントでは、
- コンパイラに多くの情報を与えることで、 よりよいエラーチェックやコード生成が 可能になる。
- (たぶん?) 参照型(&)の宣言が不要になる。
- out パラメタは、その型のデフォルト初期化子にセットされます。
この辺がそれを匂わせる話かしら?まあ値を返すんだから、受け取る方がその型で無いとメモリ破壊してしまうかも(というか上記の場合確実に)、という訳ですな。
というか D の数学関数はほぼ real 型を使うので、素直にそれに合わせとけ、という話もあるのだが。