Raw Pointers

https://doc.rust-lang.org/book/raw-pointers.html

単に*で宣言したポインタは安全ではない(何も指し示していないかもしれない)ので、unsafe内で展開して使用する。

fn main() {
    let x = 5;
    let raw = &x as *const i32;
    // println!("raw points at {}", *raw);
    let points_at = unsafe { *raw };
    println!("raw points at {}", points_at);

    let mut y = 10;
    let raw_mut = &mut y as *mut i32;
    // println!("raw points at {}", *raw_mut);
    let points_at = unsafe { *raw_mut };
    println!("raw points at {}", points_at);

    // Explicit cast:
    let i: u32 = 1;
    let p_imm: *const u32 = &i as *const u32;

    // Implicit coercion:
    let mut m: u32 = 2;
    let p_mut: *mut u32 = &mut m;

    unsafe {
        let ref_imm: &u32 = &*p_imm;
        let ref_mut: &mut u32 = &mut *p_mut;
    }
}

Macros #2

https://doc.rust-lang.org/book/macros.html

再帰的にマクロを使ったり、マクロは奥が深そう。 章の量も他の章と比べ、明らかに多い。

unreachable!が面白い。デバッグ等で活躍しそう。

if false {
    unreachable!();
}

Macros

https://doc.rust-lang.org/book/macros.html

マクロ。

/* vec!と同じ働きをするマクロ定義 */
macro_rules! myvec {
    ( $( $x:expr ),* ) => {
        {
            let mut temp_vec = Vec::new();
            $(
                temp_vec.push($x);
            )*
            temp_vec
        }
    };
}

macro_rules! o_O {
    (
        $(
            $x:expr; [ $( $y:expr ),* ]
        );*
    ) => {
        &[ $($( $x + $y ),*),* ]
    }
}

macro_rules! foo {
    ($v:ident) => (let $v = 3;);
    () => ( fn b() { println!("b"); } );
}

fn main() {
    let x: Vec<u32> = myvec![1, 2, 3];
    println!("{:?}", x);

    let a: &[i32]
        = o_O!(10; [1, 2, 3];
                20; [4, 5, 6]);
    assert_eq!(a, [11, 12, 13, 24, 25, 26]);

    foo!(x);
    println!("{}", x);
    foo!();
    b();
}
$ cargo run
[1, 2, 3]
3
b

`Deref` coercions

https://doc.rust-lang.org/book/deref-coercions.html

*も型に合わせて定義できる。

use std::ops::Deref;

struct DerefExample<T> {
    value: T,
}

impl<T> Deref for DerefExample<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.value
    }
}

fn main() {
    let x = DerefExample { value: 'a' };
    assert_eq!('a', *x);
}

Operators and Overloading

https://doc.rust-lang.org/book/operators-and-overloading.html

新たに定義した型に対して+を定義できる。

use std::ops::Add;

#[derive(Debug)]
struct Point {
    x: i32,
    y: i32,
}

impl Add for Point {
    type Output = Point;

    fn add(self, other: Point) -> Point {
        Point { x: self.x + other.x, y: self.y + other.y }
    }
}

impl Add<i32> for Point {
    type Output = f64;

    fn add(self, rhs: i32) -> f64 {
        (self.x + self.y + rhs) as f64
    }
}

fn main() {
    let p1 = Point { x: 1, y: 0 };
    let p2 = Point { x: 2, y: 3 };
    let p3 = p1 + p2;
    println!("{:?}", p3);

    let p: Point = Point { x: 1, y: 1 };
    let x: f64 = p + 2i32;
    println!("{}", x);
}
$ cargo run
    Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs
     Running `target/debug/4_32_operators_and_overloding`
Point { x: 3, y: 3 }
4