I am trying to write a macro that expands to a collection of impls
for some custom structs I'm writing. This is what I have:
pub trait ComponentWise : Clone + Copy {
fn new(x: f32, y: f32, z: f32) -> Self;
fn x(&self) -> f32;
fn y(&self) -> f32;
fn z(&self) -> f32;
fn has_nans(&self) -> bool {
f32::is_nan(self.x()) ||
f32::is_nan(self.y()) ||
f32::is_nan(self.z())
}
}
macro_rules! component_wise_impls {
($T:ty) => {
impl ComponentWise for $T {
fn new(x: f32, y: f32, z: f32) -> $T {
let x: $T = $T { vals: [x, y, z] };
debug_assert!(!x.has_nans());
x
}
};
}
pub struct Vector {
pub vals: [f32; 3]
}
component_wise_impls!(Vector);
Sadly, I'm being told:
error: unexpected token: Vector
let x: $T = $T { vals: [x, y, z] };
I'm a little surprised, since I can do Vector { vals: [x, y, z] }
, and I would think that is exactly what $T { vals: [x, y, z] };
expands to. Is there a way of writing this new
function in a macro?
This is working:
macro_rules! component_wise_impls {
($T:ident) => {
impl ComponentWise for $T {
fn new(x: f32, y: f32, z: f32) -> $T {
let x: $T = $T { vals: [x, y, z] };
debug_assert!(!x.has_nans());
x
}
}
}
}
You cannot use a ty
where an expression is needed.
From this page :
The interpolation
$argument_name
may appear in any location consistent with its fragment specifier (ie, if it is specified asident
, it may be used anywhere an identifier is permitted).
As llogiq pointed out, you have to implement the x
, y
and z
methods, so the complete code is:
pub trait ComponentWise : Clone + Copy {
fn new(x: f32, y: f32, z: f32) -> Self;
fn x(&self) -> f32;
fn y(&self) -> f32;
fn z(&self) -> f32;
fn has_nans(&self) -> bool {
f32::is_nan(self.x()) ||
f32::is_nan(self.y()) ||
f32::is_nan(self.z())
}
}
macro_rules! component_wise_impls {
($T:ident) => {
impl ComponentWise for $T {
fn new(x: f32, y: f32, z: f32) -> $T {
let x: $T = $T { vals: [x, y, z] };
debug_assert!(!x.has_nans());
x
}
fn x(&self) -> f32 {
self.vals[0]
}
fn y(&self) -> f32 {
self.vals[1]
}
fn z(&self) -> f32 {
self.vals[2]
}
}
}
}
#[derive(Copy, Clone)]
pub struct Vector {
pub vals: [f32; 3]
}
component_wise_impls!(Vector);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.