Операторы сравнения на самом деле ведут себя не так, как арифметические операторы. Разница становится очевидной при взгляде на определения признаков. Например, вот черта PartialEq
1002 *
pub trait PartialEq<Rhs = Self>
where
Rhs: ?Sized,
{
fn eq(&self, other: &Rhs) -> bool;
fn ne(&self, other: &Rhs) -> bool { ... }
}
и черта Add
pub trait Add<RHS = Self> {
type Output;
fn add(self, rhs: RHS) -> Self::Output;
}
Мы можем видеть, что черты сравнения принимают операнды по ссылке, в то время как арифметические черты принимают операнды по значению. Эта разница отражена в том, как компилятор переводит выражения оператора:
a == b ==> std::cmp::PartialEq::eq(&a, &b)
a + b ==> std::ops::Add::add(a, b)
Операнды сравнений оцениваются как выражения мест, поэтому они никогда не могут перемещать значения. Операнды арифметических операторов, с другой стороны, оцениваются как выражения значений, поэтому они перемещаются или копируются в зависимости от того, является ли тип операнда Copy
.
В результате этой разницы, если мы реализуем PartialEq
для типа A
, мы можем сравнивать не только A
и A
, но также &A
и &A
в силу разыменного приведения для операндов. С другой стороны, для Add
нам нужна отдельная реализация, чтобы иметь возможность добавлять &A
и &A
.
Я не могу ответить, почему в стандартной библиотеке реализованы «смешанные» версии для справки и значения для арифметических операторов, а не для сравнения. Я не вижу фундаментальной причины, по которой последнее не может быть сделано.