Хранение модуля как переменной в ржавчине - PullRequest
2 голосов
/ 27 октября 2019

У меня есть 2 разных модуля с одинаковой реализацией, одинаковыми функциями, типами и т. Д. Они просто делают разные вещи. Я хотел бы иметь возможность выбрать один из этих модулей во время выполнения и использовать его исключительно. Кроме того, есть несколько таких модулей, которые могут существовать или не существовать во время компиляции в зависимости от платформы, функций и т. Д. this - это ссылка на супер урезанную версию того, что я хочу. Я пытаюсь выбирать между различными gfx-hal бэкэндами. Лучшее, что я смог придумать, - это макрос, который создает оператор if для каждого возможного модуля, а затем запускает этот оператор if всякий раз, когда выполняется функция в модуле. Тем не менее, это не кажется элегантным или вообще хорошим. Так есть ли способ сохранить модули в переменной и получить к ней доступ или каким-то образом сделать это, имитирующее это?

Заранее спасибо

1 Ответ

2 голосов
/ 27 октября 2019

Вы можете сделать это, превратив каждый из ваших модулей в собственную реализацию черты, подобно тому, как gfx-rs делает что-то.

Ваш "trait" в действительности никогда не будет реализован с состоянием, а вместо этого будет набором связанных элементов, таких как функции, другие типы и т. Д.

Вы можете упаковать его как so :

#![allow(dead_code)]
mod foo {
    pub fn print() { println!("hello from foo") }
}

mod bar {
    pub fn print() { println!("hello from bar"); }
}

mod zam { // this may not exist depending on the platform, one will always exist
    pub fn print() { println!("hello from zam"); }
}

struct FOO;
struct BAR;
struct ZAM;

trait RuntimeModule {
    fn print();
}

impl RuntimeModule for FOO {
    fn print() { foo::print(); }
}

impl RuntimeModule for BAR {
    fn print() { bar::print(); }
}

impl RuntimeModule for ZAM {
    fn print() { zam::print(); }
}

fn main() {
    // Here we decide which to use
    print_module::<FOO>();
}
// This is our "entrypoint"
fn print_module<T: RuntimeModule>() {
    T::print();
}

Если мы решим, что использовать во время выполнения (в данном случае в main), мы можем затем вызвать универсальную функцию, которая будет использовать связанные типы / функции дляпринимать решения.

Обратите внимание, что вы не сможете использовать Box<dyn RuntimeModule>, если RuntimeModule содержит связанные типы, которые различны для каждой реализации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...