Dは関数の引数と戻り値の型がmutable/const/invariantのどれなのか把握するのが大変すぎる.
これを安全性を落とさずに緩和する方法が欲しい.
某掲示板のコードを少し整形したものをぺたりしてみる.
class A { int mem; this(int m) {mem=m;} const A opClone() {return new A(mem);}//手作業でクローンを作って返す const invariant(A) opInvariantClone() {return new invariant(A)(mem);}//同上 } void f(A x) {/*...*/} void g(const(A) x) {/*...*/} void h(invariant(A) x) {/*...*/} void main() { f(new A); f(new const(A));//opClone()が暗黙的に呼ばれる f(new invariant(A));//opClone()が暗黙的に呼ばれる g(new A); g(new const(A)); g(new invariant(A)); h(new A);//opInvariantClone()が暗黙的に呼ばれる h(new const(A));//opInvariantClone()が暗黙的に呼ばれる h(new invariant(A)); }
仕組み
つまりopAddなどのそれと同様にこれが
A x = new invariant(A);
これに変換され
A x = (new invariant(A)).opClone();
これが
invariant(A) x = new A;
これに変換される
invariant(A) x = (new A).opInvariantClone();
安全性を確保するために
opCloneが未定義のときにconst/invariant -> mutable
opInvariantCloneが未定義のときにmutable/const -> invariant
に変換しようとしたときは今までどおりエラーになって参照型メンバのディープコピー忘れを防止する.
真面目にこういうのが欲しいのだけどダメなのだろうか.