如何在Rust中添加相同类型的约束?

w46czmvw  于 2022-12-19  发布在  其他
关注(0)|答案(2)|浏览(129)

我必须在我定义的一个结构体上添加一个约束,特别是这个结构体使用一个名为T的泛型,它有两种类型:输入和输出。我想设置一个约束,在该约束上输入的类型与输出的类型相同。

#[derive(Debug, Clone)]
pub struct Example<T>
{
... // fields of the struct
}

换句话说,由于我使用T::Input和T::Output,所以在某些情况下,结构体A的输出是结构体B的输入,这显然是编译时的一个问题,因为我得到的错误是:expected T::Input, found T::Output所以参数是不正确的。实际上我明白问题是什么,但我不知道如何解释我想对编译器做什么。
我尝试使用where子句添加约束,试图指定“T::Input = T::Output”,但没有成功。我尝试这样做:

#[derive(Debug, Clone)]
pub struct Example<T>
where
    T::Input: From<T::Output>,
    T::Output: From<T::Input>

{
... // fields of the struct
}
55ooxyrt

55ooxyrt1#

正如kmdreko的回答所评论的那样,直接的写法应该是:

trait InOut {
    type Input;
    type Output;
}

struct Example<T> where T: InOut<Input = T::Output> {
    ...
}

不幸的是,这个方法失败了,出现了奇怪的循环依赖错误。
但是有时候,当你在泛型类型参数中使用关联类型时,需要写完整,否则会出现一些歧义错误,在这种情况下,你需要写T::Output而不是<T as InOut>::Output

trait InOut {
    type Input;
    type Output;
}

struct Example<T> where T: InOut<Input = <T as InOut>::Output> {
    ...
}

还有这个just works

3qpi33ja

3qpi33ja2#

不幸的是,这个简单的解决方案行不通:

trait InOut {
    type Input;
    type Output;
}

struct Example<T> where T: InOut<Input = T::Output> {
    ...
}
error[E0391]: cycle detected when computing the bounds for type parameter `T`
 --> src/lib.rs:6:42
  |
6 | struct Example<T> where T: InOut<Input = T::Output> {
  |                                          ^^^^^^^^^
  |
  = note: ...which immediately requires computing the bounds for type parameter `T` again
note: cycle used when computing explicit predicates of `Example`
 --> src/lib.rs:6:42
  |
6 | struct Example<T> where T: InOut<Input = T::Output> {
  |                                          ^^^^^^^^^

然而,如果类型匹配,我可以使用一个额外的trait来实现原始trait:

trait InOut {
    type Input;
    type Output;
}

trait InAndOut: InOut<Input = Self::Item, Output = Self::Item> {
    type Item;
}

impl<T, I> InAndOut for T where T: InOut<Input = I, Output = I> {
    type Item = I;
}

struct Example<T> where T: InAndOut {
    ...
}

完整示例可在playground上找到。

相关问题