![](/img/trans.png)
[英]How can I have static dispatch for a linked list containing different types all implementing a trait?
[英]It is possible to store all types implementing a trait in a list and iterate over that list?
我为许多结构( A
, B
, C
等)实现了一个特征:
pub trait ApplicableFor: Debug + Default {
unsafe fn is_applicable_for(from: *mut u8) -> bool
where
Self: Sized;
}
我需要一个方法来找到哪个结构为此方法调用返回true。 我有代码:
unsafe fn check_applicable<T: ApplicableFor>(from: *mut u8) -> bool {
T::is_applicable_for(from, to)
}
unsafe fn find_applicable(from: *mut u8) -> ApplicableFor {
if check_applicable::<A>(from) {
A::default()
} else if check_applicable::<B>(from) {
B::default()
} else if check_applicable::<C>(from) {
C::default()
} else {
panic!("Couldn't find appicable");
}
}
在实际的代码中,我有大约20个结构,因此我想将它们存储在某个地方,并使用如下代码来提高可读性:
unsafe fn find_applicable(from: *mut u8) -> ApplicableFor {
for T in list {
if check_applicable::<T>(from) {
T::default()
}
}
panic!("Couldn't find appicable");
}
我该怎么做或如何更好地重写呢?
不,Rust不直接提供您需要的那种元编程功能。 即,类型不是存在的具体事物,也不可以放入集合中。
相反,您需要代码生成。
从ApplicableFor
的简化版本开始,我们可以编写一个非常结构化的find_applicable
版本:
trait ApplicableFor {
fn is_applicable_for(from: u8) -> bool;
}
fn find_applicable(from: u8) {
if <A>::is_applicable_for(from) {
println!("Using {}", stringify!(A));
return;
}
if <B>::is_applicable_for(from) {
println!("Using {}", stringify!(B));
return;
}
if <C>::is_applicable_for(from) {
println!("Using {}", stringify!(C));
return;
}
panic!("Couldn't find any applicable types");
}
一旦建立了结构,就可以使用宏对其进行抽象:
fn find_applicable(from: u8) {
macro_rules! find_one {
($ty:ty) => {
if <$ty>::is_applicable_for(from) {
println!("Using {}", stringify!($ty));
return;
}
}
}
find_one!(A);
find_one!(B);
find_one!(C);
panic!("Couldn't find any applicable types");
}
如果我们想重复这种“为这种类型的列表做些事情”的概念怎么办? 另一个宏:
macro_rules! each_type {
($one_type_macro:tt) => {
$one_type_macro!(A);
$one_type_macro!(B);
$one_type_macro!(C);
};
}
fn find_applicable(from: u8) {
macro_rules! find_one {
($ty:ty) => {
if <$ty>::is_applicable_for(from) {
println!("Using {}", stringify!($ty));
return;
}
}
}
each_type!(find_one);
panic!("Couldn't find any applicable types");
}
对each_type!
的实现来说太each_type!
? 创建一个宏,该宏创建另一个将与另一个宏一起调用的宏:
macro_rules! gen_each_type {
($($ty:ty),*) => {
macro_rules! each_type {
($one_type_macro:tt) => {
$($one_type_macro!($ty);)*
};
}
};
}
gen_each_type![A, B, C];
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.