仅当结构具有字段时如何使用宏实现特征

问题描述 投票:0回答:1

我希望始终在任何结构上调用宏,但仅在此类结构具有名为 ˋ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ˋ纯粹是一个名称,而不是一个结构定义。

我该如何解决这个问题?

rust
1个回答
0
投票

您为宏提供的模式实际上必须与宏的其中一个分支相匹配。 这些模式是结构定义,而不仅仅是结构名称。 因此,如果您将完整的结构定义传递给宏,它将匹配。

请注意,您的宏还需要发出结构定义。

例如:

#[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
类型令牌来解决此问题。

此外,请注意,您匹配的模式排除了在结构体或字段上指定宏的可能性。 例如,这使得将派生宏应用于生成的结构变得不可能。

您应该考虑编写一个派生宏来处理这种情况,因为它不需要您在宏中指定整个结构定义语法。

© www.soinside.com 2019 - 2024. All rights reserved.