简体   繁体   English

是否可以将实现特征的所有类型存储在列表中并在该列表上进行迭代?

[英]It is possible to store all types implementing a trait in a list and iterate over that list?

I have a trait implemented for many structs ( A , B , C , etc.): 我为许多结构( ABC等)实现了一个特征:

pub trait ApplicableFor: Debug + Default {
    unsafe fn is_applicable_for(from: *mut u8) -> bool
    where
        Self: Sized;
}

I need a method which finds which struct returns true for this method call. 我需要一个方法来找到哪个结构为此方法调用返回true。 I have the code: 我有代码:

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");
    }
}

In the real code, I have around 20 structs, so I want to store them somewhere and use code like this for readability: 在实际的代码中,我有大约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");
}

How can I do this or how can I rewrite this better? 我该怎么做或如何更好地重写呢?

No, Rust does not directly offer the kind of metaprogramming features you need. 不,Rust不直接提供您需要的那种元编程功能。 Namely, a type is not a concrete thing that exists or can be put into a collection. 即,类型不是存在的具体事物,也不可以放入集合中。

Instead, you need code generation. 相反,您需要代码生成。

Starting from a simplified version of ApplicableFor , we can write a very structured version of find_applicable : 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");
}

Once we have established the structure, then we can start abstracting it with macros: 一旦建立了结构,就可以使用宏对其进行抽象:

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");
}

What if we want to repeat this concept of "do something for this list of types"? 如果我们想重复这种“为这种类型的列表做些事情”的概念怎么办? Another macro: 另一个宏:

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");
}

Too much noise for the implementation of each_type! each_type!的实现来说太each_type! ? Create a macro that creates another macro which will be called with another macro: 创建一个宏,该宏创建另一个将与另一个宏一起调用的宏:

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.

相关问题 如何对包含不同类型的链表进行静态调度,所有类型都实现了一个特征? - How can I have static dispatch for a linked list containing different types all implementing a trait? 为实现 trait 的所有类型实现 trait - Implement a trait for all types implementing a trait 为所有使用 const 参数实现特性的类型实现特性 - Implementing a trait for all types implementing a trait with const parameter 递归迭代List / Array - Recursively iterate over List/Array 是否可以为除一个类型子集之外的所有类型都适用的特征创建通用实现? - Is it possible to create a generic impl for a trait that works with all but one subset of types? 我如何遍历我的通用列表列表中的所有元素<t>向后并做预期的操作?</t> - How can I iterate over all elements in my generic list List<T> backwards and do the intended operation? 如何使用通配符迭代此通用List? - How to iterate over this generic List with wildcards? 如何使用foreach遍历混合列表? - How to iterate over a mixed list using foreach? 允许列表中所有类型的通用类型 - Allow all types of generic types in a List 在使用泛型而不是原始类型时实现List而不是ArrayList - Implementing List instead of ArrayList while using generics instead of raw types
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM