Rust by Example — страница 27 из 66

struct Single(A);

//            ^ Here is `Single`s first use of the type `A`.

// Here, `` precedes the first use of `T`, so `SingleGen` is a generic type.

// Because the type parameter `T` is generic, it could be anything, including

// the concrete type `A` defined at the top.

struct SingleGen(T);

fn main() {

// `Single` is concrete and explicitly takes `A`.

let _s = Single(A);

// Create a variable `_char` of type `SingleGen`

// and give it the value `SingleGen('a')`.

// Here, `SingleGen` has a type parameter explicitly specified.

let _char: SingleGen = SingleGen('a');

// `SingleGen` can also have a type parameter implicitly specified:

let _t    = SingleGen(A); // Uses `A` defined at the top.

let _i32  = SingleGen(6); // Uses `i32`.

let _char = SingleGen('a'); // Uses `char`.

}

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

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

See also:

structs

Functions

The same set of rules can be applied to functions: a type T becomes generic when preceded by .

Using generic functions sometimes requires explicitly specifying type parameters. This may be the case if the function is called where the return type is generic, or if the compiler doesn't have enough information to infer the necessary type parameters.

A function call with explicitly specified type parameters looks like: fun::().

struct A;          // Concrete type `A`.

struct S(A);       // Concrete type `S`.

struct SGen(T); // Generic type `SGen`.

// The following functions all take ownership of the variable passed into

// them and immediately go out of scope, freeing the variable.

// Define a function `reg_fn` that takes an argument `_s` of type `S`.

// This has no `` so this is not a generic function.

fn reg_fn(_s: S) {}

// Define a function `gen_spec_t` that takes an argument `_s` of type `SGen`.

// It has been explicitly given the type parameter `A`, but because `A` has not

// been specified as a generic type parameter for `gen_spec_t`, it is not generic.

fn gen_spec_t(_s: SGen) {}

// Define a function `gen_spec_i32` that takes an argument `_s` of type `SGen`.

// It has been explicitly given the type parameter `i32`, which is a specific type.

// Because `i32` is not a generic type, this function is also not generic.

fn gen_spec_i32(_s: SGen) {}

// Define a function `generic` that takes an argument `_s` of type `SGen`.

// Because `SGen` is preceded by ``, this function is generic over `T`.

fn generic(_s: SGen) {}

fn main() {

// Using the non-generic functions

reg_fn(S(A));          // Concrete type.

gen_spec_t(SGen(A));   // Implicitly specified type parameter `A`.

gen_spec_i32(SGen(6)); // Implicitly specified type parameter `i32`.

// Explicitly specified type parameter `char` to `generic()`.

generic::(SGen('a'));

// Implicitly specified type parameter `char` to `generic()`.

generic(SGen('c'));

}

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

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

See also:

functions and structs

Implementation

Similar to functions, implementations require care to remain generic.


#![allow(unused)]

fn main() {

struct S; // Concrete type `S`

struct GenericVal(T); // Generic type `GenericVal`


// impl of GenericVal where we explicitly specify type parameters:

impl GenericVal {} // Specify `f32`

impl GenericVal {} // Specify `S` as defined above


// `` Must precede the type to remain generic

impl GenericVal {}

}

struct Val {

val: f64,

}

struct GenVal {

gen_val: T,

}

// impl of Val

impl Val {

fn value(&self) ->&f64 {

&self.val

}

}

// impl of GenVal for a generic type `T`

impl GenVal {

fn value(&self) ->&T {

&self.gen_val

}

}

fn main() {

let x = Val { val: 3.0 };

let y = GenVal { gen_val: 3i32 };

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

}

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

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

See also:

functions returning references, impl, and struct

Traits

Of course traits can also be generic. Here we define one which reimplements the Drop trait as a generic method to drop itself and an input.

// Non-copyable types.

struct Empty;

struct Null;

// A trait generic over `T`.

trait DoubleDrop {

// Define a method on the caller type which takes an

// additional single parameter `T` and does nothing with it.

fn double_drop(self, _: T);

}

// Implement `DoubleDrop