Define a macro to reduce the amount of code

How to define a macro to reduce the amount of code like this (View on Github)

impl_cast_same_type!(i8);
impl_cast_int_to_int!(i8, i16);
impl_cast_int_to_int!(i8, i32);
impl_cast_int_to_int!(i8, i64);
impl_cast_int_to_int!(i8, isize);
impl_cast_int_to_uint!(i8, u8);
impl_cast_int_to_uint!(i8, u16);
impl_cast_int_to_uint!(i8, u32);
impl_cast_int_to_uint!(i8, u64);
impl_cast_int_to_uint!(i8, usize);
impl_cast_int_to_float!(i8, f32);
impl_cast_int_to_float!(i8, f64);

impl_cast_int_to_int!(i16, i8);
impl_cast_same_type!(i16);
impl_cast_int_to_int!(i16, i32);
impl_cast_int_to_int!(i16, i64);
impl_cast_int_to_int!(i16, isize);
impl_cast_int_to_uint!(i16, u8);
impl_cast_int_to_uint!(i16, u16);
impl_cast_int_to_uint!(i16, u32);
impl_cast_int_to_uint!(i16, u64);
impl_cast_int_to_uint!(i16, usize);
impl_cast_int_to_float!(i16, f32);
impl_cast_int_to_float!(i16, f64);

I have to repeat this pattern for all integer and float types.

Here's how it's done in conv.

1 Like

Something like this would be helpful. Note that you still need to repeat about a half of arguments, this is a fundamental limit of using macros.

// test macros
macro_rules! impl_cast_same_type { ($t:ty) => (println!("impl_cast_same_type!({});", stringify!($t))) }
macro_rules! impl_cast_int_to_int { ($f:ty, $t:ty) => (println!("impl_cast_int_to_int!({}, {});", stringify!($f), stringify!($t))) }
macro_rules! impl_cast_int_to_uint { ($f:ty, $t:ty) => (println!("impl_cast_int_to_uint!({}, {});", stringify!($f), stringify!($t))) }
macro_rules! impl_cast_int_to_float { ($f:ty, $t:ty) => (println!("impl_cast_int_to_float!({}, {});", stringify!($f), stringify!($t))) }
macro_rules! impl_cast_uint_to_int { ($f:ty, $t:ty) => (println!("impl_cast_uint_to_int!({}, {});", stringify!($f), stringify!($t))) }
macro_rules! impl_cast_uint_to_uint { ($f:ty, $t:ty) => (println!("impl_cast_uint_to_uint!({}, {});", stringify!($f), stringify!($t))) }
macro_rules! impl_cast_uint_to_float { ($f:ty, $t:ty) => (println!("impl_cast_uint_to_float!({}, {});", stringify!($f), stringify!($t))) }
macro_rules! impl_cast_float_to_int { ($f:ty, $t:ty) => (println!("impl_cast_float_to_int!({}, {});", stringify!($f), stringify!($t))) }
macro_rules! impl_cast_float_to_uint { ($f:ty, $t:ty) => (println!("impl_cast_float_to_uint!({}, {});", stringify!($f), stringify!($t))) }
macro_rules! impl_cast_float_to_float { ($f:ty, $t:ty) => (println!("impl_cast_float_to_float!({}, {});", stringify!($f), stringify!($t))) }

macro_rules! impl_cast {
    (
        $(i $i:ty => $(i $ii:ty),*, $(u $iu:ty),*, $(f $if_:ty),*);*;
        $(u $u:ty => $(i $ui:ty),*, $(u $uu:ty),*, $(f $uf:ty),*);*;
        $(f $f:ty => $(i $fi:ty),*, $(u $fu:ty),*, $(f $ff:ty),*);*;
    ) => ({
        $(impl_cast_same_type!($i);
          $(impl_cast_int_to_int!($i, $ii);)*
          $(impl_cast_int_to_uint!($i, $iu);)*
          $(impl_cast_int_to_float!($i, $if_);)*)*
        $(impl_cast_same_type!($u);
          $(impl_cast_uint_to_int!($u, $ui);)*
          $(impl_cast_uint_to_uint!($u, $uu);)*
          $(impl_cast_uint_to_float!($u, $uf);)*)*
        $(impl_cast_same_type!($f);
          $(impl_cast_float_to_int!($f, $fi);)*
          $(impl_cast_float_to_uint!($f, $fu);)*
          $(impl_cast_float_to_float!($f, $ff);)*)*
    })
}

fn main() {
    impl_cast! {
        i i8    =>       i i16, i i32, i i64, i isize, u u8, u u16, u u32, u u64, u usize, f f32, f f64;
        i i16   => i i8,        i i32, i i64, i isize, u u8, u u16, u u32, u u64, u usize, f f32, f f64;
        i i32   => i i8, i i16,        i i64, i isize, u u8, u u16, u u32, u u64, u usize, f f32, f f64;
        i i64   => i i8, i i16, i i32,        i isize, u u8, u u16, u u32, u u64, u usize, f f32, f f64;
        i isize => i i8, i i16, i i32, i i64,          u u8, u u16, u u32, u u64, u usize, f f32, f f64;
        u i8    => i i8, i i16, i i32, i i64, i isize,       u u16, u u32, u u64, u usize, f f32, f f64;
        u i16   => i i8, i i16, i i32, i i64, i isize, u u8,        u u32, u u64, u usize, f f32, f f64;
        u i32   => i i8, i i16, i i32, i i64, i isize, u u8, u u16,        u u64, u usize, f f32, f f64;
        u i64   => i i8, i i16, i i32, i i64, i isize, u u8, u u16, u u32,        u usize, f f32, f f64;
        u isize => i i8, i i16, i i32, i i64, i isize, u u8, u u16, u u32, u u64,          f f32, f f64;
        f f32   => i i8, i i16, i i32, i i64, i isize, u u8, u u16, u u32, u u64, u usize,        f f64;
        f f64   => i i8, i i16, i i32, i i64, i isize, u u8, u u16, u u32, u u64, u usize, f f32       ;
    }
}
1 Like