Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper way to `use` in a macro

I'm trying to write a macro that needs to use a few items. This is suitable for one use per file, but it feels dirty to me. Is there a better way to reference the items directly, such as impl std::ops::Add for $t or something? Thanks!

#[macro_export]
macro_rules! implement_measurement {
    ($($t:ty)*) => ($(
        // TODO: Find a better way to reference these...
        use std::ops::{Add,Sub,Div,Mul};
        use std::cmp::{Eq, PartialEq};
        use std::cmp::{PartialOrd, Ordering};

        impl Add for $t {
            type Output = Self;

            fn add(self, rhs: Self) -> Self {
                Self::from_base_units(self.get_base_units() + rhs.get_base_units())
            }
        }

        impl Sub for $t {
            type Output = Self;

            fn sub(self, rhs: Self) -> Self {
                Self::from_base_units(self.get_base_units() - rhs.get_base_units())
            }
        }

        // ... others ...
    ))
}
like image 331
jocull Avatar asked Oct 31 '22 01:10

jocull


1 Answers

You can either use the trait, or you can refer to it with the full path:

struct Something {
    count: i8,
}

impl std::fmt::Display for Something {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}", self.count)
    }
}

Note that inside a module, item paths are relative, so you either need to use some number of super or an absolute path (the better choice, in my opinion):

mod inner {
    struct Something {
        count: i8,
    }

    impl ::std::fmt::Display for Something {
        fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
            write!(f, "{}", self.count)
        }
    }
}

There's a middle ground where you use the module, but not the trait:

use std::fmt;

impl fmt::Display for Something {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.count)
    }
}

And if you are just worried about typing, you can alias the module, but it's my belief that making it too short makes it harder to understand:

use std::fmt as f;

impl f::Display for Something {
    fn fmt(&self, f: &mut f::Formatter) -> f::Result {
        write!(f, "{}", self.count)
    }
}
like image 169
Shepmaster Avatar answered Dec 19 '22 23:12

Shepmaster