1 个不稳定版本
0.1.0 | 2023年6月6日 |
---|
#1041 in 进程宏
17KB
178 行
Traitify
你应该使用这个crate吗?
不。可能不是。
为什么我要创建这个crate?
好吧,有时候你有一个泛型类型,需要将其传递给一个不能有泛型的函数。如果Rust有类似于以下语法的语法那就太棒了:
struct Foo<BAR, const FIZZ: usize>;
fn buzz(foo: &Foo<dyn, dyn>) {}
看我是怎么做的?在泛型类型的位置使用dyn
的这种假想语法会动态地将它转换为特质对象!酷吧?
遗憾的是,这种语法并不是真实的,实际上并没有类似的东西。
那么,有哪些可行的方法呢?
基本上,我能想到两种方法。
如果你知道所有泛型的不同变体,你可以创建一个枚举,并在该枚举上重新实现所有的Foo
函数。
如果你不知道,那么你可以创建一个包含Foo
所有函数的特质,并为Foo
实现该特质。但仅由一个类型实现的特质感觉是错误的。它感觉像是写了一个C头文件,我就完成写头文件的工作了。
这就是这个crate的作用所在!
这个crate只包含一个宏,你可以将其应用到impl
块上。你告诉它特质的名称以及它应该忽略哪些泛型类型。
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!
以下是一个(可能不完整)的列表,列出了哪些函数最终出现在生成的特质中
- 函数必须是公开的(这不是技术要求,但否则你将通过公开的特质泄露私有函数)
- 函数不能有在dyn列表中的泛型类型的参数
- 函数不能指定ABI
- 函数必须有一个接收器参数(self, &self 或 &mut self)。它将在特质中,但为了对象安全,会加上一个
Self: Sized
绑定。对特质对象来说不是很实用,但它添加起来很简单。
不能擦除生命周期。我认为应该是可能的,但我还没有实现。
依赖项
~265–710KB
~17K SLoC