Нужно ли добавлять код, чтобы избежать приведения, когда одного интерфейса уже недостаточно - PullRequest
0 голосов
/ 12 ноября 2018
// ===== library code: =====

trait Sate { // Or in C++ imagine this is a class containing only pure virtuals.
    fn ready(&mut self, ..);
    fn terminate(&mut self, ..);
    fn timeout(&mut self, .. );
    fn ....; // a few more functions
    fn as_any(&mut self) -> &mut Any; // for downcasting in Rust; not necessary in C++
}

states: HashMap<u32, Rc<RefCell<State>>>; // Or in C++ just a map of numbers to shared-ptr of State

fn event_loop_on_some_trigger(trigger_for: u32, trigger: Blah) {
    let state = states[trigger_for];
    if trigger == for_timeout { state.borrow_mut().timeout(...) }
    else if trigger = for_readiness { state.borrow_mut().timeout(...) }
    ...
}


//==== User Code: ====

struct Type0 { ... }
impl State for Type0 { /* provide concrete impls */ } // In C++ this would be inheritance for Type0

struct Type1 { ... }
impl State for Type1 { /* provide concrete impls */ } // In C++ this would be inheritance for Type1

// ... etc.

Я использовал эту библиотеку, и все работало нормально.Но теперь есть несколько типов, которые должны выполнять какую-то конкретную работу, которая выходит за рамки того, что есть в черте State выше.Так что я, кажется, постепенно сталкиваюсь с «проблемой выражений» в дизайне.Я не управляю библиотекой, предоставляющей черту и цикл обработки событий, и даже если бы я это сделал, я бы не добавил туда 2 или 3 дополнительных функции, так как это неправильно, поскольку она будет использоваться только для некоторых конкретных типов иэто тоже время от времени.

Кроме того, у меня есть карта в коде пользователя, такая как HashMap<u32, SomeDetail>, которая соответствует карте в стеке потоков цикла событий выше.Поэтому, если мне нужно выполнить специальную операцию для одного из типов, я могу получить значение u32 для состояния (анализируя SomeDetail или что-то еще), получить состояние из карты в цикле обработки событий и уменьшить его.к типу для вызова одной из специальных функций.

На данный момент в C ++ я, вероятно, использовал бы static_cast<>, так как я уверен, что это тип (если только в загрузке идентификаторов нет ошибок)или это распределение, которое было бы логической ошибкой в ​​программе).В Rust я вынужден использовать downcast_mut (dynamic_cast в C ++), с которым у меня все в порядке (до сих пор у меня никогда не возникало никаких ошибок во время выполнения, показывая, что логика правильна, и static_cast былион также был бы доступен в Safe-Rust).

Теперь мой вопрос - я читал, что кастинг - это плохой дизайн и т. д. Поэтому я думал, что я мог бы сделать по-другому здесь.Одной из идей было сохранить слабые (или сильные, если нам все равно) ссылки на карте, которые есть в моем коде пользователя.Таким образом, хотя цикл обработки событий использует карту, он должен запустить некоторую функцию для State, но я бы использовал свою карту, чтобы получить конкретный тип всякий раз, когда я этого захочу, и вызывать функцию для него.Однако, поскольку мой код находится за пределами потока события цикла, мне пришлось бы добавить Mutex к состояниям, что бесполезно в 99% случаев, так как большую часть времени это вызов события Eventloop и типы, выполняющие то, для чего они кодированы.

  1. Должен ли я хранить несколько карт (ссылок) на конкретные типы, специальные функции, которые я хочу иногда вызывать и шлепать туда мьютекс?
  2. Просто в этом случае сделайте dynamic_castи это оправданно?
  3. Eventloop должен был быть шаблонизирован, чтобы дать пользователю возможность сохранить некоторое состояние в стеке потока Eventloop и иметь дело с ним.В этом случае я бы сохранил несколько своих карт <u32, ConcreteTypeReferences>, чтобы я мог публиковать запрос в цикле событий в редких случаях, когда я хочу взаимодействовать с конкретными типами, и они могут продолжать жить без мьютекса или атомарной ссылки-четные объекты (в Rust Rc - это не-атомный ref-smart smart-ptr, я не знаю, есть ли эквивалент в C ++)

Последний вариант, а также частично 1-й требуетУ меня есть доступ к этому коду - это скорее список пожеланий, но я просто хочу знать, что было бы предложением, если бы это было так.В отсутствие этого (2) dynamic_cast кажется единственным жизнеспособным решением?

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