トレイト境界

ジェネリクスを扱うときは、型に何らかのトレイトの実装を要求して、そのトレイトのメソッドを呼び出せるようにしたいことがよくあります。

これは T: Trait で指定できます。

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

fn duplicate<T: Clone>(a: T) -> (T, T) {
    (a.clone(), a.clone())
}

struct NotCloneable;

fn main() {
    let foo = String::from("foo");
    let pair = duplicate(foo);
    println!("{pair:?}");
}
  • NotCloneable を作成して、それを duplicate に渡してみましょう。

  • 複数のトレイトが必要な場合は、+ で連結します。

  • where 句も示しましょう。受講者はコードを読むときにこれに出会います。

    // Copyright 2022 Google LLC
    // SPDX-License-Identifier: Apache-2.0
    
    fn duplicate<T>(a: T) -> (T, T)
    where
        T: Clone,
    {
        (a.clone(), a.clone())
    }
    • パラメータが多い場合、関数シグネチャをすっきりさせられます。
    • 追加の機能があり、より強力です。
      • もし質問されたら、追加の機能とは : の左側の型を Option<T> のように任意にできることだと説明してください。
  • Rust は(まだ)特殊化をサポートしていないことに注意してください。たとえば、元の duplicate があるとき、特殊化した duplicate(a: u32) を追加することは無効です。