关于rust:如何为枚举实现PartialEq?

How to implement PartialEq for an enum?

我的定义如下:

1
2
3
4
enum Either<T, U> {
    Left(T),
    Right(U),
}

我将如何获得与此类型等效的#[derive(PartialEq)]?我想使用match表达式,例如:

1
2
3
4
5
6
7
8
9
10
impl<T: PartialEq, U: PartialEq> PartialEq for Either<T, U> {
    fn eq(&self, other: &Either<T, U>) -> bool {
        use Either::*;
        match (*self, *other) {
            (Left(ref a), Left(ref b)) => a == b,
            (Right(ref a), Right(ref b)) => a == b,
            _ => false,
        }
    }
}

这消耗了*self*other,即使我只需要match表达式使用它,也会导致错误:

1
2
3
4
5
6
7
8
9
10
11
error[E0507]: cannot move out of borrowed content
 --> src/lib.rs:9:16
  |
9 |         match (*self, *other) {
  |                ^^^^^ cannot move out of borrowed content

error[E0507]: cannot move out of borrowed content
 --> src/lib.rs:9:23
  |
9 |         match (*self, *other) {
  |                       ^^^^^^ cannot move out of borrowed content

通常,您只需要使用#[derive(PartialEq)],如下所示:

1
2
3
4
5
#[derive(PartialEq)]
enum Either<T, U> {
    Left(T),
    Right(U),
}

这将生成用于为您实现特征的代码。 Rust编程语言描述了实现细节。

有时,您想直接实现特征。这可能是因为默认版本太具体或太通用。

您遇到的错误是您需要对引用进行模式匹配,而不是尝试取消引用:

1
2
3
4
5
6
7
8
9
10
11
impl<T: PartialEq, U: PartialEq> PartialEq for Either<T, U> {
    fn eq(&self, other: &Self) -> bool {
        use Either::*;

        match (self, other) {
            (&Left(ref a), &Left(ref b)) => a == b,
            (&Right(ref a), &Right(ref b)) => a == b,
            _ => false,
        }
    }
}

创建元组时,将被取消引用的项移动到元组中,从而放弃所有权。如果拥有match *foo,则不必放弃所有权。

在现代Rust中,您可以用更少的噪音编写相同的东西,因为在模式匹配时会发生更多的隐式引用/取消引用:

1
2
3
4
5
6
7
8
9
10
impl<T: PartialEq, U: PartialEq> PartialEq for Either<T, U> {
    fn eq(&self, other: &Self) -> bool {
        use Either::*;
        match (self, other) {
            (Left(a), Left(b)) => a == b,
            (Right(a), Right(b)) => a == b,
            _ => false,
        }
    }
}