Rust: 缩短通用类型约束

4
有没有办法在Rust中缩短通用类型的边界? 这是我不得不在很多结构体实现等代码中添加的繁琐内容:
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 {
...

首先,您可以导入这些特征,这样您就不必每次都使用完全限定的方式来使用它们。 - Peter Hall
2个回答

5

我有时会意识到某个特定特征的所有出现都与其他特征相关联。在你的情况下,如果 AppState 总是与 CloneSerialize 出现,你可以在状态顶部要求它们:

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

如果没有,您仍然可以定义一个辅助特性

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

需要 State : AuxAppState

然后,要自动推导出 AuxAppState,您需要为每种类型都进行 impl,并且这些类型还要 implement StateCloneSerialize

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)* {}
    }
}

所有这些都有可能在某一天通过特质别名实现。

此外,我开始只在必要的地方添加特质边界。例如,在许多情况下,结构体定义本身并不依赖于特质边界,只有实现中需要,因此我开始省略它们在结构体中的使用,只在实现上保留它们。


3
你可以使用新的 traits 和通用实现来完成这个功能:
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
{
    ... 
}

沙盒环境


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接