When defining implementations in macros, it might be useful to access a struct members type to avoid having to pass it as an extra argument. (see this question)
impl PartialEq<u32> for MyStruct { ... }
Is there a way to access the type of a struct member without knowing in advance which type it is?
impl PartialEq<typeof(MyStruct.member)> for MyStruct { ... }
In case it's helpful, this is an abbreviated example of why I'm interested to do this:
struct_bitflag_impl!(
pub struct MyFlag(u8);,
MyFlag, u8);
// ^^ how to avoid having this extra arg?
// (Used by ``impl PartialEq<$t_internal> for $p``)
// couldn't it be discovered from `MyFlag.0` ?
// the macro
macro_rules! struct_bitflag_impl {
($struct_p_def: item, $p:ident, $t_internal:ty) => {
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
$struct_p_def
impl ::std::ops::BitAnd for $p {
type Output = $p;
fn bitand(self, _rhs: $p) -> $p { $p(self.0 & _rhs.0) }
}
impl ::std::ops::BitOr for $p {
type Output = $p;
fn bitor(self, _rhs: $p) -> $p { $p(self.0 | _rhs.0) }
}
impl ::std::ops::BitXor for $p {
type Output = $p;
fn bitxor(self, _rhs: $p) -> $p { $p(self.0 ^ _rhs.0) }
}
impl ::std::ops::Not for $p {
type Output = $p;
fn not(self) -> $p { $p(!self.0) }
}
// support comparison with the base-type.
impl PartialEq<$t_internal> for $p {
fn eq(&self, other: &t_internal) -> bool {
self.0 == *other
}
}
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// How to avoid using 't_internal' here?
}
}
No, a general typeof(Type::field)
that can be used in type position does not exist.
Regarding the example in the question, it looks like you are expecting a special kind of item: a tuple-struct with only one field. So, instead of accepting an $item
fragment, you can simulate the syntax yourself:
macro_rules! foo {
(pub struct $name:ident ( $ty:ident ) ) => {
pub struct $name($ty);
impl $name {
pub fn bar() {
println!("{}", stringify!($ty));
}
}
}
}
foo!(
pub struct Peter(u8)
);
fn main() {
Peter::bar();
}
That way you only have to specify everything once. However, this obviously only works with one kind of tuple-struct definition, not all kinds of items. But your use case suggests that you are more or less only interested in this special case.
If you want to allow different kinds of struct definitions, you just need to add more macro-rules to the macro to allow for different syntax. To see an example, here is code to allow for pub
and non-pub
tuple-struct definitions. But this could be expanded even more.
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