I'm trying to implement a macro which implements the Add trait for a struct, like so:
macro_rules! implement_add {
($t:ty) => {
impl std::ops::Add for $t {
type Output = $t;
fn add(self, rhs: $t) -> $t {
$t(self.0 + rhs.0) // error on this line
}
}
}
}
pub struct Length(f64);
implement_add!(Length);
fn main() {}
However, this gives an error on the indicated line:
<anon>:6:17: 6:19 error: unexpected token: `Length`
<anon>:6 $t(self.0 + rhs.0) // error on this line
^~
This makes no sense to me. Especially since, if I replace $t
there with Length
, it compiles fine. Am I doing something wrong in my macro?
Playground: http://is.gd/EIEKub
You can't pass as function argument. But if function is a macro this is possible.
You can use it inside a function, but it is not scoped to the function. So, in your example, the second definitions of a macro will be a redefinition and generate an error.
To define a macro that uses arguments, you insert parameters between the pair of parentheses in the macro definition that make the macro function-like. The parameters must be valid C identifiers, separated by commas and optionally whitespace.
You've stumbled on a subtle bit of Rust's type system. Length
is a type, but Length()
is a function. These exist in different namespaces.
One work around is to extend your macro to accept a type and a function:
macro_rules! implement_add {
($t:ty, $c:ident) => {
impl std::ops::Add for $t {
type Output = $t;
fn add(self, rhs: $t) -> $t {
$c(self.0 + rhs.0) // error on this line
}
}
}
}
pub struct Length(f64);
implement_add!(Length, Length);
fn main() {}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With