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

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

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

pub struct MenuState<I> {
    pub items: Vec<I>,
}

以下代码无法编译(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) { }
}

(注:MenuView的实施需要ToStringCopy的约束)

我知道如何通过添加一些幻影数据来解决这个问题,使I上的MenuView成为通用的(参见playground),但它很难看,似乎太复杂了.我觉得上面粘贴的代码只需要一些语法上的修正.

有没有一个简单的解决方案,既不改变View的特性,也不涉及幻影?

如果由于某种根本原因不能定义语法修复,那是什么原因呢?

推荐答案

在不更改View特征的情况下,PhantomData是正确的解决方案,您的泛型必须出现在特征或 struct 中的某个位置.State是与MenuView"关联"的东西,因此没有其他方法可以将其包括在内.

然而,您的 case 可能表明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>) {}
}

这或多或少地转换了您的原始特征,从对具有StateMenuView实现View,到对MenuView实现ViewState.

Rust相关问答推荐

Rust,polars CSV:有没有一种方法可以从impll BufRead(或任何字节迭代器)中读取CSV?

使用nom将任何空白、制表符、白线等序列替换为单个空白

将此字符串转换为由空格字符分隔的空格

是否有可能同时避免不兼容的不透明类型和代码重复?

铁 rust 中的共享对象实现特征

如何用Axum/Tower压缩Html内容?

我应该将哪些文件放入我的GitHub存储库

Rust函数的返回值不能引用局部变量或临时变量

如何迭代属性以判断相等性?

详尽的匹配模式绑定

如何基于常量在Rust中跳过一个测试

Rust中是否可以在不复制的情况下从另一个不可变向量创建不可变向量?

有没有办法隐式绑定 let/match 操作的成员?

使用在功能标志后面导入的类型,即使未启用功能标志

bcrypt 有长度限制吗?

为什么传递 option.as_ref 的行为不同于使用匹配块并将内部映射到 ref 自己?

如何创建递归borrow 其父/创建者的 struct ?

使用 `.` 将 T 转换为 &mut T?

传递 Option<&mut T> 时何时需要 mut

如何在不设置精度的情况下打印浮点数时保持尾随零?