美文网首页
rust重载运算符

rust重载运算符

作者: Wu杰语 | 来源:发表于2024-07-03 20:49 被阅读0次

1. 运算符重载

在上一篇文章《rust泛型编程范式》中我们讲了关联类型,例子如下

pub trait Iterator {
    type Item;
    fn next(&mut self) -> Option<Self::Item>;
}

对于运算符重载,有些运算符trait定义了关联类型,有些没有定义了,什么时候用关联类型什么时候不用关联类型,我们分别看看,最后得出结论。

2. 带有关联类型的重载

2.1 一元运算符

  • std::ops::Neg
  • std::ops::Not

其定义如下:

trait Neg {
    type Output;
    fn neg(self) -> Self::Output;
}

trait Not {
    type Output;
    fn not(self) -> Self::Output;
}

一个例子如下:

#[derive(Clone, Copy, Debug)]
struct Complex<T> {
    /// 复数的实部
    re: T,

    /// 复数的虚部
    im: T,
}

use std::ops::Neg;

impl<T> Neg for Complex<T>
where
    T: Neg<Output = T>,
{
    type Output = Complex<T>;
    fn neg(self) -> Complex<T> {
        Complex {
            re: -self.re,
            im: -self.im,
        }
    }
}

2.1 二元运算符

  • std::ops::Add
  • std::ops::Sub
  • std::ops::Mul
  • std::ops::Div
  • std::ops::Rem
  • std::ops::BitAnd
  • std::ops::BitOr
  • std::ops::BitXor
  • std::ops::Shl
  • std::ops::Shr

其trait定义如下:

trait Add<Rhs = Self> {
    type Output;
    fn add(self, rhs: Rhs) -> Self::Output;
}

trait BitXor<Rhs = Self> {
    type Output;
    fn bitxor(self, rhs: Rhs) -> Self::Output;
}

一个例子如下:

use std::ops::Add;

impl Add for Complex<i32> {
    type Output = Complex<i32>;
    fn add(self, rhs: Self) -> Self {
        Complex {
            re: self.re + rhs.re,
            im: self.im + rhs.im,
        }
    }
}

2.3 索引(非mut)

  • std::ops::Index

其trait定义如下

trait Index<Idx> {
    type Output: ?Sized;
    fn index(&self, index: Idx) -> &Self::Output;
}

3. 不带关联类型的重载

3.1 复合赋值运算符

  • std::ops::AddAssign
  • std::ops::SubAssign
  • std::ops::MulAssign
  • std::ops::DivAssign
  • std::ops::RemAssign
  • std::ops::BitAndAssign
  • std::ops::BitOrAssign
  • std::ops::BitXorAssign
  • std::ops::ShlAssign
  • std::ops::ShrAssign

其trait定义如下

trait AddAssign<Rhs = Self> {
    fn add_assign(&mut self, rhs: Rhs);
}

一个例子如下:

use std::ops::AddAssign;

impl<T> AddAssign for Complex<T>
where
    T: AddAssign<T>,
{
    fn add_assign(&mut self, rhs: Complex<T>) {
        self.re += rhs.re;
        self.im += rhs.im;
    }
}

3.2 比较运算符

  • std::cmp::PartialEq
  • std::cmp::PartialOrd

其trait定义如下:

trait PartialEq<Rhs = Self>
where
    Rhs: ?Sized,
{
    fn eq(&self, other: &Rhs) -> bool;
    fn ne(&self, other: &Rhs) -> bool {
        !self.eq(other)
    }
}

trait PartialOrd<Rhs = Self>: PartialEq<Rhs>
where
    Rhs: ?Sized,
{
    fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
    fn lt(&self, other: &Rhs) -> bool { ... }
    fn le(&self, other: &Rhs) -> bool { ... }
    fn gt(&self, other: &Rhs) -> bool { ... }
    fn ge(&self, other: &Rhs) -> bool { ... }
}

一个例子如下:

impl<T: PartialEq> PartialEq for Complex<T> {
    fn eq(&self, other: &Complex<T>) -> bool {
        self.re == other.re && self.im == other.im
    }
}

3.3 索引(mut)

  • std::ops::IndexMut

其trait定义如下

trait IndexMut<Idx>: Index<Idx> {
    fn index_mut(&mut self, index: Idx) -> &mut Self::Output;
}

4 小结

什么时候用关联类型,观察上述trait定义,有两个重要发现:

  • 当存在返回值且返回值为泛型定义是,定义了关联类型。
  • 当不需要泛型返回值或者无返回值,就没有关联类型,无返回值一般是修改自身,因此参数是&mut self。

按照这两个发现,我们可以规范一下自己何时用trait的关联类型。

相关文章

  • 运算符重载及其他约定

    7.1 重载算术运算符 重载二元算术运算符 重载复合赋值运算符 重载一元运算符 重载比较运算符 等号运算符:‘eq...

  • C++ 部分运算符重载

    可重载的运算符 不可重载的运算符和符号 重载运算符为类的成员函数 重载运算符为友元函数 重载赋值运算符 重载流插入...

  • 2019-07-11 运算符的重载

    运算符的重载 重载运算符 (“::”,“.*”,“.”,“?:”)不能被重载。 重载运算符时,不能改变其本质,如不...

  • 运算符重载

    一.+号运算符重载 二.<<号运算符重载 三.指针运算符重载(智能指针)

  • C++运算符重载-下篇 (Boolan)

    C++运算符重载-下篇 (Boolan) 本章内容:1. 运算符重载的概述2. 重载算术运算符3. 重载按位运算符...

  • C++运算符重载-上篇 (Boolan)

    C++运算符重载-上篇 (Boolan) 本章内容:1. 运算符重载的概述2. 重载算术运算符3. 重载按位运算符...

  • C++重载

    重载 C++语言规定: 重载的运算符要保持原运算符的意义。只能对已有的运算符重载,不能增加新的运算符。重载的运算符...

  • C++运算符重载详解

    运算符重载规则 1.被重载的运算符必须是已经存在的C++运算符,不能重载自己创建的运算符; 2.运算符被重载之后,...

  • 第十一章 使用类

    运算符重载 运算符重载是一种形式的C++多态。运算符重载将重载的概念扩展到运算符上,允许赋予C++运算符多种含义。...

  • 4.0 C++远征:重载运算符

    重载运算符 [TOC] 四、重载运算符 ​ 概念 : 给原有运算符赋予新功能。 ​ 本质 : 函数重载。 ...

网友评论

      本文标题:rust重载运算符

      本文链接:https://www.haomeiwen.com/subject/kbwbcjtx.html