Rust: укоротить родовые c границы типа - PullRequest
3 голосов
/ 30 апреля 2020

Есть ли способ сократить границы типа generi c в ржавчине? Это беспорядок, который я должен наложить на многие структуры. Impls et c.:

pub struct IncomingClientMessageWithAddress<State, Msg>
    where State: AppState + Clone + serde::Serialize + serde::de::DeserializeOwned + std::marker::Unpin + 'static,
          Msg: AppEvent + Clone + serde::Serialize + serde::de::DeserializeOwned + std::marker::Unpin + 'static {
...

Я в основном хочу сделать что-то подобное (я знаю, что ниже не работает для черт) :

type MyStateAlias = AppState + Clone + serde::Serialize + serde::de::DeserializeOwned + std::marker::Unpin + 'static;
type MyEventAlias = AppEvent + Clone + serde::Serialize + serde::de::DeserializeOwned + std::marker::Unpin + 'static;


pub struct IncomingClientMessageWithAddress<State, Msg>
    where State: MyStateAlias,
          Msg: MyEventAlias {
...

Ответы [ 2 ]

5 голосов
/ 30 апреля 2020

Я иногда осознавал, что все вхождения определенной черты связаны с другими чертами. В вашем случае, если AppState всегда происходит с Clone и Serialize, вам может потребоваться это в верхней части состояния:

trait AppState : Clone + Serialize {/*...*/}

Если нет, вы все равно можете определить вспомогательную черту

trait AuxAppState: AppState + Clone + Serialize {/*...*/}

и потребовать State : AuxAppState.

Затем, чтобы автоматически получить AuxAppState, вам потребуется impl для каждого типа, который также impl элементы State, Clone и Serialize:

impl<T> AuxAppState for T where T: AppState + Clone + Serialize {}

Наконец, определение и impl добавление AuxAppState может быть выполнено макросом для сохранения некоторых нажатий клавиш :

macro_rules! auxiliary_trait{
    ($traitname: ident, $($t:tt)*) => {
        trait $traitname : $($t)* {}
        impl<T> $traitname for T where T: $($t)* {}
    }
}

Все это возможно сделать за один день с псевдонимами признаков .

Более того, я начал требовать границы признаков только там, где они действительно необходимы , Например, во многих случаях само определение struct не полагается на границы признаков, только impl, поэтому я начал опускать их на struct, оставляя их только в impl.

3 голосов
/ 30 апреля 2020

Для этого вы можете использовать новые черты с общими реализациями:

use serde::Serialize;
use serde::de::DeserializeOwned;
use std::marker::Unpin;

pub trait AppState {}
pub trait AppEvent {}

pub trait StateTrait : AppState + Clone + Serialize + DeserializeOwned + Unpin + 'static {}
impl<T : AppState + Clone + Serialize + DeserializeOwned + Unpin + 'static> StateTrait for T {}
pub trait EventTrait : AppEvent + Clone + Serialize + DeserializeOwned + Unpin + 'static {}
impl<T : AppEvent + Clone + Serialize + DeserializeOwned + Unpin + 'static> EventTrait for T {}

pub struct IncomingClientMessageWithAddress<State, Msg>
    where State: StateTrait, Msg: EventTrait
{
    ... 
}

детская площадка

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