1个不稳定版本
0.1.0 | 2023年6月6日 |
---|
#21 在 #impl-block
在 traitify 中使用
12KB
172 行
Traitify
你应该使用这个crate吗?
不。可能不是。
我为什么创建这个crate?
嗯,有时候你有一个泛型类型,需要将其传递给一个不能有泛型的函数。如果Rust有类似的语法那就太棒了
struct Foo<BAR, const FIZZ: usize>;
fn buzz(foo: &Foo<dyn, dyn>) {}
看我在那里做了什么?这个想象中的语法中在泛型类型的地方用dyn
替换,会即时将其变成一个trait对象!酷吧?
遗憾的是这个语法并不存在,而且真的没有类似的东西。
那么,有哪些可行的方法呢?
基本上有两种方法。
如果你知道你泛型的所有不同变体,你可以创建一个枚举,并在该枚举上重新实现所有 Foo
函数。
如果你不知道,你可以创建一个包含 Foo
所有函数的trait,并为 Foo
实现这个trait。但写一个只由一个类型实现的trait感觉是不对的。感觉就像写一个C头文件,我就完成了头文件的编写。
这就是这个crate的作用所在!
这个crate只包含一个可以应用于impl
块的宏。你告诉它所需的trait名称和应该忽略哪些泛型类型。
use traitify::traitify;
struct Foo<BAR, const FIZZ: usize> {
data: [BAR; FIZZ],
};
#[traitify(FooDynFizz, dyn = [FIZZ])]
#[traitify(FooDynBAR, dyn = [BAR])]
#[traitify(FooDynAll, dyn = [FIZZ, BAR])]
impl<BAR, const FIZZ: usize> Foo<BAR, FIZZ> {
pub fn print_greeting(&self) {
println!("Hallo vriendjes en vriendinnetjes!");
}
}
#[test]
fn compiles() {
let foo = Foo::<u8, 4> { data: [0; 4] };
let dyn_foo: &dyn FooDynAll = &foo;
dyn_foo.print_greeting();
}
现在,我尽力让这个宏处理尽可能多的语法。但如果你发现有些东西不工作,而应该是工作的,那么请提交一个问题或PR!
以下是一个(可能不完整)的列表,说明哪些函数会出现在生成的trait中
- 函数必须是公开的(这不是技术要求,否则你将通过公开的trait泄漏私有函数)
- 函数不得有属于dyn列表的泛型类型的参数
- 函数不得指定ABI
- 函数必须有一个接收器参数(self, &self 或 &mut self)。它将在特质中,但会为对象安全性添加一个
Self: Sized
约束。对于特质对象来说并不十分有用,但添加起来很简单。
无法擦除生命周期。我认为应该可以,但我还没有做到。
依赖项
~250–700KB
~17K SLoC