使用泛型类型作为关联类型,没有幻像数据

Den*_*ret 6 rust

我有一个定义关联类型的特征:

pub trait View: Default {
    type State;
    fn draw(&mut self, state: &mut Self::State);
}
Run Code Online (Sandbox Code Playgroud)

我有一个适合State关联类型的类型,但它是通用的:

pub struct MenuState<I> {
    pub items: Vec<I>,
}
Run Code Online (Sandbox Code Playgroud)

以下代码无法编译(rust 1.66),因为I不受约束:

#[derive(Default)]
pub struct MenuView {
    // fields here
}
impl<I: ToString + Copy> View for MenuView {
    type State = MenuState<I>;
    fn draw(&mut self, _state: &mut Self::State) { }
}
Run Code Online (Sandbox Code Playgroud)

(注: 的实施需要ToString和约束)CopyMenuView

我知道如何通过添加一些幻像数据来实现MenuView通用I(请参阅游乐场)来解决这个问题,但它很丑陋,而且看起来太复杂了。我觉得上面粘贴的代码只需要一些语法修复。

是否有一个简单的解决方案,无需改变View特征且不涉及幻影?

如果由于某些根本原因而无法定义语法修复,那么原因是什么?

Sta*_*eur 7

在不更改View特征的情况下,PhantomData正确的解决方案是,您的泛型必须出现在特征或结构中的某个位置。State是“关联”的东西MenuView,因此除了包含它之外没有其他方法。

但是,您的情况可能表明View没有很好地定义您的用法,也许泛型比关联类型更合适。喜欢:

pub trait View<State>: Default {
    fn draw(&mut self, state: &mut State);
}

#[derive(Default)]
pub struct MenuState<I> {
    pub items: Vec<I>,
}

#[derive(Default)]
pub struct MenuView {}

impl<I: ToString + Copy + Default> View<MenuState<I>> for MenuView {
    fn draw(&mut self, _state: &mut MenuState<I>) {}
}
Run Code Online (Sandbox Code Playgroud)

这或多或少地改变了你原来的特质,从实现forView到实现一个for 。MenuViewStateViewStateMenuView