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

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

<p id="see_also_38"><strong><a l:href="#see_also_38">See also:</a></strong></p>

std::fmt and traits

<p id="where_clauses"><strong><a l:href="#where_clauses">Where clauses</a></strong></p>

A bound can also be expressed using a where clause immediately before the opening {, rather than at the type's first mention. Additionally, where clauses can apply bounds to arbitrary types, rather than just to type parameters.

Some cases that a where clause is useful:

   • When specifying generic types and bounds separately is clearer:

impl MyTrait for YourType {}

// Expressing bounds with a `where` clause

impl MyTrait for YourType where

A: TraitB + TraitC,

D: TraitE + TraitF {}

   • When using a where clause is more expressive than using normal syntax. The impl in this example cannot be directly expressed without a where clause:

use std::fmt::Debug;

trait PrintInOption {

fn print_in_option(self);

}

// Because we would otherwise have to express this as `T: Debug` or

// use another method of indirect approach, this requires a `where` clause:

impl PrintInOption for T where

Option: Debug {

// We want `Option: Debug` as our bound because that is what's

// being printed. Doing otherwise would be using the wrong bound.

fn print_in_option(self) {

println!("{:?}", Some(self));

}

}

fn main() {

let vec = vec![1, 2, 3];

vec.print_in_option();

}

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

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

<p id="see_also_39"><strong><a l:href="#see_also_39">See also:</a></strong></p>

RFC, struct, and trait

<p id="new_type_idiom"><strong><a l:href="#new_type_idiom">New Type Idiom</a></strong></p>

The newtype idiom gives compile time guarantees that the right type of value is supplied to a program.

For example, an age verification function that checks age in years, must be given a value of type Years.

struct Years(i64);

struct Days(i64);

impl Years {

pub fn to_days(&self) -> Days {

Days(self.0 * 365)

}

}

impl Days {

/// truncates partial years

pub fn to_years(&self) -> Years {

Years(self.0 / 365)

}

}

fn old_enough(age: &Years) -> bool {

age.0 >= 18

}

fn main() {

let age = Years(5);

let age_days = age.to_days();

println!("Old enough {}", old_enough(&age));

println!("Old enough {}", old_enough(&age_days.to_years()));

Перейти на страницу:

Похожие книги