The following fails to compile, and I'm currently at a loss as to why.
pub struct Vec3<T> {
pub x: T,
pub y: T,
pub z: T,
}
macro_rules! impl_vector {
($V:ident { $($field:ident),+ }) => {
impl $V<f32> {
pub fn squared_magnitude(&self) -> f32 {
$(self.$field * self.$field)++
}
}
}
}
impl_vector!(Vec3 { x, y, z });
I would expect this to expand to:
impl Vec3<f32> {
pub fn squared_magnitude(&self) -> f32 {
self.x * self.x+self.y * self.y+self.z * self.z
}
}
krdln
February 26, 2017, 1:30am
2
Your $( ... )++
is unfortunately getting parsed as $( ... )+ +
. So it expands to self.x*self.x self.y*self.y ...
, hence the error.
I'm not sure if that's a bug or an expected behaviour, anyway, as a workaround you could just change it to $( ... + )+ 0.0
That makes sense! Somehow it didn't occur to me. Unfortunate.
The f32 was just a simplified example, 0.0 is not going to work on the end. But I could do this for now (using num_traits):
impl<T: Copy + Mul<T,Output=T> + Add<T,Output=T> + Zero> $VecN<T>{
#[inline]
pub fn squared_magnitude(&self) -> T {
$(self.$field * self.$field + )+ T::zero()
}
}
krdln
February 26, 2017, 1:45am
4
If you don't want to use the Zero
(although the Zero
solution is perfectly fine), then you can also explicitly parse the first identifier: $first:ident $(, $field:ident)*
, so you it serves you the purpose of the T::zero()
. Also, maybe writing .add
instead of +
would work.