Rust宏接受类型与通用参数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Rust宏接受类型与通用参数相关的知识,希望对你有一定的参考价值。

我有一个实现特征的宏,impl_Trait!()。现在,它适用于没有泛型参数的类型,但我不确定如何将类型参数添加到impl关键字。

macro_rules! impl_FooTrait {
    ($name:ty) => {
        impl $crate::FooTrait for $name { ... }
    };
}

struct Bar(i32);
impl_FooTrait!(Bar);
// All OK

struct Baz<'a>(&'a i32);
impl_FooTrait!(Baz<'a>);
// use of undeclared lifetime name `'a`
答案

以免责声明的方式提交此答案:可能有更好的方法来做到这一点。我还不熟悉宏观的土地。

你可以使用tt(单一标记)标识符来接受你想要的另一个宏臂(playground link

macro_rules! impl_FooTrait {
    ($name:ty, $lifetime:tt) => {
        impl<$lifetime> $crate::FooTrait for $name {  }
    };
    ($name:ty) => {
        impl $crate::FooTrait for $name {  }
    };
}

struct Bar(i32);
impl_FooTrait!(Bar);

struct Baz<'a>(&'a i32);
impl_FooTrait!(Baz<'a>, 'a); // Use and declare the lifetime during macro invocation

看起来我觉得有点奇怪。我有兴趣看到任何其他有替代品的答案。

这是一个实际实现的例子:Playground link

另一答案

这是一个老问题,但似乎在这里似乎没有一个好的答案。我有一个部分解决方案,虽然它匹配一些不正确的输入,我不能让它适用于生命周期参数。

#[macro_export]
macro_rules! impl_trait {
    // this evil monstrosity matches <A, B: T, C: S+T>
    // but because there is no "zero or one" rule, also <D: S: T>
    ($ty:ident < $( $N:ident $(: $b0:ident $(+$b:ident)* )* ),* >) =>
    {
        impl< $( $N $(: $b0 $(+$b)* )* ),* >
            $crate::path::to::Trait
            for $ty< $( $N ),* >
        {
            // function implementations go here
        }
    };
    // match when no type parameters are present
    ($ty:ident) => {
        impl_trait!($ty<>);
    };
}

Example (play)

以上是关于Rust宏接受类型与通用参数的主要内容,如果未能解决你的问题,请参考以下文章

打字稿:如何制作接受对象的类型,其键匹配通用但所有值都是值参数的映射函数

Rust 通用编程概念

为啥我的可变参数宏不能正确接受任何参数?

接受 Result<T, E> 作为函数参数是惯用的 Rust 吗?

「Rust笔记」Rust之自定义宏写法

rust鼠标宏会被封号吗