我希望始终在任何结构上调用宏,但仅在此类结构具有名为 ˋstatusˋ:
的字段的情况下才实现
TryInto<u8>
#[macro_export]
macro_rules! impl_status {
(
struct $name:ident {
status: $status_type:ty,
$($rest:tt)*
}
) => {
#[allow(dead_code)]
impl TryInto<u8> for $name {
type Error = ();
fn try_into(
self,
) -> Result<u8, Self::Error> {
todo!()
}
}
};
(
struct $name:ident {
$($field:ident : $type:ty),*
}
) => {
impl TryInto<()> for $name {
type Error = ();
fn try_into(self) -> Result<(), Self::Error> {
Ok(())
}
}
};
}
pub struct HasStatusStruct {
status: u8
}
impl_status!{HasStatusStruct}
我知道为什么这不起作用:ˋHasStatusStructˋ纯粹是一个名称,而不是一个结构定义。
我该如何解决这个问题?
您为宏提供的模式实际上必须与宏的其中一个分支相匹配。 这些模式是结构定义,而不仅仅是结构名称。 因此,如果您将完整的结构定义传递给宏,它将匹配。
请注意,您的宏还需要发出结构定义。
例如:
#[macro_export]
macro_rules! impl_status {
(
struct $name:ident {
status: $status_type:ty,
$($rest:tt)*
}
) => {
struct $name {
status: $status_type,
$($rest)*
}
#[allow(dead_code)]
impl TryInto<u8> for $name {
type Error = ();
fn try_into(
self,
) -> Result<u8, Self::Error> {
todo!()
}
}
};
(
struct $name:ident {
$($field:ident : $type:ty),*
}
) => {
struct $name {
$($field : $type),*
}
impl TryInto<()> for $name {
type Error = ();
fn try_into(self) -> Result<(), Self::Error> {
Ok(())
}
}
};
}
impl_status! {
struct HasStatusStruct {
status: u8,
}
}
请注意,我必须从结构中删除
pub
,因为模式不需要它。 例如,您可以通过采用可选的 vis
类型令牌来解决此问题。
此外,请注意,您匹配的模式排除了在结构体或字段上指定宏的可能性。 例如,这使得将派生宏应用于生成的结构变得不可能。
您应该考虑编写一个派生宏来处理这种情况,因为它不需要您在宏中指定整个结构定义语法。