Rust のギモン その 2
前回、Point3D と Vector3D を実装するにあたって演算子オーバーロードを使用したのだけれど、std::ops::Add 等の trait で実装すべきメソッドは
fn add(self, rhs: Rhs) -> Self::Output
とあるように self も rhs も move してしまう。なので、そのまま Vector3D に対して実装すると、
let a: = Vector3D::new(1.0, 2.0, 3.0); let b: = Vector3D::new(4.0, 5.0, 6.0); let c = a + b;
とした場合に a と b は move out してしまい、以降使用できなくなる。実際のところ、この計算では a, b のどちらも変更しないから、後でまた a, b を使っても問題ないし、使いたくなることもあり得る。なので代わりに &Vector3D に対して Add trait を実装した。
impl Add<&Vector3D> for &Vector3D { type Output = Vector3D; fn add(self, v: &Vector3D) -> Self::Output { Vector3D::new(self.x + v.x, self.y + v.y, self.z + v.z) } }
これなら
let a: = Vector3D::new(1.0, 2.0, 3.0); let b: = Vector3D::new(4.0, 5.0, 6.0); let c = &a + &b;
とすることにより c を得てからも a, b 双方とも利用できる。ただ、これだと毎回 & を付けなければならないのが面倒だし、何より 3 つ以上 add したいなら
&(&a + &b) + &c;
のように書かなければならず、可読性が著しく低下する。これを回避しようとすると、型 T に対して
- &T + &T (使用例: &a + &b)
- &T + T (使用例: &a + (&b + &c))
- T + &T (使用例: (&a + &b) + &c)
- T + T (使用例: (&a + &b) + (&c + &d))
の 4 つの add を実装しなければならない。これはこれで面倒な上、誤って move out させてしまう可能性も生じる。
何か良い方法はないのだろうか。Copy を derive する以外で。