Rust におけるジェネリック関数の定義

RustRustBeginner
今すぐ練習

This tutorial is from open-source community. Access the source code

💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください

はじめに

この実験では、Rust でジェネリック関数を定義する方法を学びます。関数をジェネリックにするには、型 T の前に <T> を付けます。場合によっては、ジェネリック関数を呼び出す際に型パラメータを明示的に指定する必要があります。これは fun::<A, B,...>() という構文を使って行うことができます。提供されたコードは、Rust でのジェネリック関数の使用方法を示しており、ジェネリックでない関数の例も含まれています。

注: 実験でファイル名が指定されていない場合、好きなファイル名を使うことができます。たとえば、main.rs を使って、rustc main.rs &&./main でコンパイルして実行することができます。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL rust(("Rust")) -.-> rust/DataTypesGroup(["Data Types"]) rust(("Rust")) -.-> rust/FunctionsandClosuresGroup(["Functions and Closures"]) rust(("Rust")) -.-> rust/MemorySafetyandManagementGroup(["Memory Safety and Management"]) rust(("Rust")) -.-> rust/AdvancedTopicsGroup(["Advanced Topics"]) rust/DataTypesGroup -.-> rust/integer_types("Integer Types") rust/DataTypesGroup -.-> rust/type_casting("Type Conversion and Casting") rust/FunctionsandClosuresGroup -.-> rust/function_syntax("Function Syntax") rust/FunctionsandClosuresGroup -.-> rust/expressions_statements("Expressions and Statements") rust/MemorySafetyandManagementGroup -.-> rust/lifetime_specifiers("Lifetime Specifiers") rust/AdvancedTopicsGroup -.-> rust/operator_overloading("Traits for Operator Overloading") subgraph Lab Skills rust/integer_types -.-> lab-99345{{"Rust におけるジェネリック関数の定義"}} rust/type_casting -.-> lab-99345{{"Rust におけるジェネリック関数の定義"}} rust/function_syntax -.-> lab-99345{{"Rust におけるジェネリック関数の定義"}} rust/expressions_statements -.-> lab-99345{{"Rust におけるジェネリック関数の定義"}} rust/lifetime_specifiers -.-> lab-99345{{"Rust におけるジェネリック関数の定義"}} rust/operator_overloading -.-> lab-99345{{"Rust におけるジェネリック関数の定義"}} end

関数

同じルールのセットを関数にも適用できます。型 T の前に <T> がある場合、その型はジェネリックになります。

ジェネリック関数を使用する場合、型パラメータを明示的に指定する必要があることがあります。これは、戻り型がジェネリックな関数を呼び出す場合や、コンパイラが必要な型パラメータを推論するのに十分な情報を持っていない場合に該当します。

明示的に指定された型パラメータを持つ関数呼び出しは、fun::<A, B,...>() のようになります。

struct A;          // 具体的な型 `A`。
struct S(A);       // 具体的な型 `S`。
struct SGen<T>(T); // ジェネリック型 `SGen`。

// 次の関数はすべて、渡された変数の所有権を取得し、
// 直ちにスコープ外になり、変数を解放します。

// 型 `S` の引数 `_s` を取る関数 `reg_fn` を定義します。
// これには `<T>` がないので、これはジェネリック関数ではありません。
fn reg_fn(_s: S) {}

// 型 `SGen<T>` の引数 `_s` を取る関数 `gen_spec_t` を定義します。
// 型パラメータ `A` が明示的に与えられていますが、`A` が `gen_spec_t` のジェネリック型パラメータとして指定されていないため、これはジェネリックではありません。
fn gen_spec_t(_s: SGen<A>) {}

// 型 `SGen<i32>` の引数 `_s` を取る関数 `gen_spec_i32` を定義します。
// 型パラメータ `i32` が明示的に与えられており、これは特定の型です。
// `i32` はジェネリック型ではないため、この関数もジェネリックではありません。
fn gen_spec_i32(_s: SGen<i32>) {}

// 型 `SGen<T>` の引数 `_s` を取る関数 `generic` を定義します。
// `SGen<T>` の前に `<T>` があるため、この関数は `T` についてジェネリックです。
fn generic<T>(_s: SGen<T>) {}

fn main() {
    // ジェネリックでない関数を使用する
    reg_fn(S(A));          // 具体的な型。
    gen_spec_t(SGen(A));   // 暗黙的に指定された型パラメータ `A`。
    gen_spec_i32(SGen(6)); // 暗黙的に指定された型パラメータ `i32`。

    // `generic()` に明示的に型パラメータ `char` を指定する。
    generic::<char>(SGen('a'));

    // `generic()` に暗黙的に型パラメータ `char` を指定する。
    generic(SGen('c'));
}

まとめ

おめでとうございます!あなたは関数の実験を完了しました。あなたのスキルを向上させるために、LabExでさらに多くの実験を行って練習することができます。