ジェネリック

ジェネリックは違う型の間で同じ機能を提供するのに使う機構です。 これはコードの重複を減らすのに有用ですが、複雑な構文が必要になります。 ジェネリック型を使うにはきちんと機能するか最新の注意を払わなければ いけません。そして、型パラメータとしての使い方が最も単純で一般的です。

ジェネリック型の型パラメータはカギ括弧とキャメルケース(<Aaa, Bbb, ...>) が使われます。「ジェネリックな型パラメータ」は普通<T>で表します。Rustでは、 「ジェネリック」には「ジェネリックな型パラメータ<T>を1つ以上受け入れるもの」という 意味もあります。ジェネリックな型パラメータを指定された場合それはジェネリック型になり、 それ以外はすべて具象型(非ジェネリック)として扱われます。

例として、あらゆる型Tの引数を受け取るジェネリック関数fooを定義します。

fn foo<T>(arg: T) { ... }

T<T>によってジェネリックな型パラメータとして指定されているので、(arg: T)のように ジェネリック型として使うことができます。前にTが構造体として定義されていたとしても、 ジェネリックが優先されます。

次の例で、手を動かしながらジェネリックを学んでいきましょう。

// 具象型`A`
struct A;

// `Single`型の宣言では、前に`<A>`がないことと、`A`が具象型として定義されていることから、
// `Single`は具象型になります。
struct Single(A);
//            ^ `Single`内で初めて型`A`が出てくる。

// ここで、ジェネリックな型パラメータ`<T>`が出てくるので、`T`はジェネリック型になり、
// `SingleGen`もジェネリック型になります。`T`どんな型にもなり得るので、上で定義した
// 型`A`も受け取れます。

fn main() {
    // `Single`は具象型で、`A`をとります。
    let _s = Single(A);
    
    // `SingleGen<char>`型の変数`_char`を作り、
    // `SingleGen('a')`で初期化します。
    // ここで、`SingleGen`には明示的に型パラメータが与えられています。
    let _char: SingleGen<char> = SingleGen('a');

    // `SingleGen`型の変数には明示的に型パラメータを与えなくても良い。
    let _t    = SingleGen(A); // Uses `A` defined at the top.
    let _i32  = SingleGen(6); // Uses `i32`.
    let _char = SingleGen('a'); // Uses `char`.
}

こちらも参照: