演算子

演算子オーバーロードは std::ops のトレイトを通じて実装されます。

// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0

#[derive(Debug, Copy, Clone)]
struct Point {
    x: i32,
    y: i32,
}

impl std::ops::Add for Point {
    type Output = Self;

    fn add(self, other: Self) -> Self {
        Self { x: self.x + other.x, y: self.y + other.y }
    }
}

fn main() {
    let p1 = Point { x: 10, y: 20 };
    let p2 = Point { x: 100, y: 200 };
    println!("{p1:?} + {p2:?} = {:?}", p1 + p2);
}

議論のポイント:

  • &Point に対して Add を実装することもできます。これはどのような状況で役立つでしょうか?
    • 回答: Add:addself を消費します。演算子をオーバーロードする対象の型 TCopy でない場合は、&T に対しても演算子をオーバーロードすることを検討すべきです。これにより、呼び出し側で不要なクローンを避けられます。
  • Output が関連型なのはなぜでしょうか? これをメソッドの型パラメータにすることはできるでしょうか?
    • 短い答え: 関数の型パラメータは呼び出し側が制御しますが、関連型(Output のようなもの)はトレイトの実装者が制御します。
  • 2 つの異なる型に対して Add を実装することもできます。たとえば、 impl Add<(i32, i32)> for Point はタプルを Point に加算します。

Not トレイト(! 演算子)は、C 系言語の同じ演算子のように引数を bool に変換しないため、注目に値します。代わりに、整数型に対しては数値の各ビットを反転します。これは算術的には、引数を -1 から減算することと等価です: !5 == -6