Выбрать главу

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Структуры

Тот же набор правил применяется и к функциям: тип T становится обобщённым, когда предшествует <T>.

При использовании обобщённых функций, иногда требуется явно указывать тип данных параметров. Это может быть необходимо в случае, если вызываемая функция возвращает обобщённый тип или у компилятора недостаточно информации для вывода необходимого типа данных.

Вызов функции с явно указанными типами данных параметров выглядит так: fun::<A, B, ...>().

struct A; // Конкретный тип `A`.

struct S(A); // Конкретный тип `S`.

struct SGen<T>(T); // Обобщённый тип `SGen`.

// Все следующие функции становятся владельцем переменной, переданной в них.

// После передачи, она сразу выходит из области видимости и освобождается.

// Объявляем функцию `reg_fn`, которая принимает аргумент `_s` типа `S`.

// Здесь отсутствует `<T>`, поэтому это не обобщённая функция.

fn reg_fn(_s: S) {}

// Объявляем функцию `gen_spec_t`, которая принимает аргумент `_s` типа `SGen<T>`.

// В ней явно задан параметр типа `A`, но поскольку `A` не был указан

// как параметр обобщённого типа для `gen_spec_t`, то он не является обобщённым.

fn gen_spec_t(_s: SGen<A>) {}

// Объявляем функцию `gen_spec_i32`, которая принимает аргумент `_s` типа `SGen<i32>`.

// В ней явно задан тип `i32`, который является определённым типом.

// Поскольку `i32` не является обобщённым типом, эта функция

// также не является обобщённой.

fn gen_spec_i32(_s: SGen<i32>) {}

// Объявляем функцию `generic`, которая принимает аргумент `_s` типа `SGen<T>`.

// Поскольку `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`.

// Явно определён тип параметра `char` в `generic()`.

generic::<char>(SGen('a'));

// Неявно определён параметр типа `char` в `generic()`.

generic(SGen('c'));

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Функции и структуры

Подобно функциям, реализации требуют выполнения некоторых условий, чтобы оставаться обобщёнными.

#![allow(unused)]

fn main() {

struct S; // Конкретный тип `S`

struct GenericVal<T>(T); // Обобщенный тип `GenericVal`

// Реализация GenericVal, где мы явно указываем типы данных параметров:

impl GenericVal<f32> {} // Указываем тип `f32`

impl GenericVal<S> {} // Указываем тип `S`, который мы определили выше

// `<T>` должен указываться перед типом, чтобы оставаться обобщённым

impl<T> GenericVal<T> {}

}

struct Val {

vaclass="underline" f64,

}

struct GenVal<T> {

gen_vaclass="underline" T,

}

// Реализация Val

impl Val {

fn value(&self) -> &f64 {

&self.val

}

}

// Реализация GenVal для обобщённого типа `T`

impl<T> GenVal<T> {

fn value(&self) -> &T {

&self.gen_val

}

}

fn main() {

let x = Val { vaclass="underline" 3.0 };

let y = GenVal { gen_vaclass="underline" 3i32 };

println!("{}, {}", x.value(), y.value());