Нет, 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!
? Создайте макрос, который создает другой макрос, который будет вызываться с другим макросом:
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];