#template #impl-block #proc-macro #procedural #generate #pattern #foo-bar

impl-template

一个基于简单模板生成 impl-blocks 的过程宏

1个版本 (0个不稳定版)

1.0.0-alpha2020年2月9日

#1449过程宏

MIT/Apache

11KB
177 代码行

impl-template

impl-template 是一个Rust编程语言的过程宏,允许你定义“impl”项的模板,并根据配置将其展开为多个实例。

从某种意义上讲,如果你事先知道所有要实现的类型,那么它就像是编译时的泛型 impl。

用法

trait Foo {}

struct Bar;
struct Baz;

#[impl_template]
impl Foo for ((Bar, Baz)) {

}

这将生成以下代码

impl Foo for Bar {

}

impl Foo for Baz {

}

高级用法

impl-template 会寻找双元组的模式。这些是语法上有效的Rust代码,但据我所知,相当无用,因此不应该在日常Rust代码中出现。

多个双元组模式

你可以拥有任意数量的这些双元组。 impl-template 会将这些双元组创建成笛卡尔积,并据此生成相应的 impl-blocks。

trait GenericFoo<T, S> { }

struct Bar;
struct Baz;

struct One;
struct Two;
struct Three;

struct Alpha;
struct Beta;

#[impl_template]
impl GenericFoo<((Bar, Baz)), ((Alpha, Beta))> for ((One, Two, Three)) { }

上面的片段将展开为12个 impl blocks (2 * 3 * 2)。

引用类型

impl-template 允许你在模板块中引用类型。它会为方案中的每个双元组生成一个假标识符 __TYPE{}__,其中 {} 被替换为基于0的索引。

我们可以扩展 GenericFoo,在其中我们需要命名类型参数的方法

trait GenericFoo<T, S> {
    fn my_fn(arg1: T, arg2: S) -> Self;
}

struct Bar;
struct Baz;

struct One;
struct Two;
struct Three;

struct Alpha;
struct Beta;

#[impl_template]
impl GenericFoo<((Bar, Baz)), ((Alpha, Beta))> for ((One, Two, Three)) {
    fn my_fn(_arg1: __TYPE0__, _arg2: __TYPE1__) -> __TYPE2__ {
        unimplemented!()
    }
}

上面的代码展开为以下(非穷尽列表)

impl GenericFoo<Bar, Alpha> for One {
    fn my_fn(_arg1: Bar, _arg2: Alpha) -> One {
        unimplemented!()
    }
}

impl GenericFoo<Bar, Beta> for One {
    fn my_fn(_arg1: Bar, _arg2: Beta) -> One {
        unimplemented!()
    }
}

换句话说,__TYPE0__ 是第一个双元组 ((Bar, Baz)) 的类似迭代器的占位符,__TYPE1__ 用于第二个,等等。

依赖关系

~2MB
~43K SLoC