mirror of
https://github.com/ahgamut/rust-ape-example.git
synced 2024-11-25 01:01:01 +00:00
56 lines
1.7 KiB
Rust
56 lines
1.7 KiB
Rust
// ./src/generics/phantom/testcase_units.md
|
|
|
|
|
|
use std::ops::Add;
|
|
use std::marker::PhantomData;
|
|
|
|
/// Create void enumerations to define unit types.
|
|
#[derive(Debug, Clone, Copy)]
|
|
enum Inch {}
|
|
#[derive(Debug, Clone, Copy)]
|
|
enum Mm {}
|
|
|
|
/// `Length` is a type with phantom type parameter `Unit`,
|
|
/// and is not generic over the length type (that is `f64`).
|
|
///
|
|
/// `f64` already implements the `Clone` and `Copy` traits.
|
|
#[derive(Debug, Clone, Copy)]
|
|
struct Length<Unit>(f64, PhantomData<Unit>);
|
|
|
|
/// The `Add` trait defines the behavior of the `+` operator.
|
|
impl<Unit> Add for Length<Unit> {
|
|
type Output = Length<Unit>;
|
|
|
|
// add() returns a new `Length` struct containing the sum.
|
|
fn add(self, rhs: Length<Unit>) -> Length<Unit> {
|
|
// `+` calls the `Add` implementation for `f64`.
|
|
Length(self.0 + rhs.0, PhantomData)
|
|
}
|
|
}
|
|
|
|
fn part0() {
|
|
// Specifies `one_foot` to have phantom type parameter `Inch`.
|
|
let one_foot: Length<Inch> = Length(12.0, PhantomData);
|
|
// `one_meter` has phantom type parameter `Mm`.
|
|
let one_meter: Length<Mm> = Length(1000.0, PhantomData);
|
|
|
|
// `+` calls the `add()` method we implemented for `Length<Unit>`.
|
|
//
|
|
// Since `Length` implements `Copy`, `add()` does not consume
|
|
// `one_foot` and `one_meter` but copies them into `self` and `rhs`.
|
|
let two_feet = one_foot + one_foot;
|
|
let two_meters = one_meter + one_meter;
|
|
|
|
// Addition works.
|
|
println!("one foot + one_foot = {:?} in", two_feet.0);
|
|
println!("one meter + one_meter = {:?} mm", two_meters.0);
|
|
|
|
// Nonsensical operations fail as they should:
|
|
// Compile-time Error: type mismatch.
|
|
//let one_feter = one_foot + one_meter;
|
|
}
|
|
|
|
pub fn main() {
|
|
part0();
|
|
}
|
|
|