Rust中有多个操作员超载

问题描述

我知道可以通过使用特质在Rust中实现运算符重载。在C ++中,对于同一操作符和相同的struct,还可以有多个操作符重载,并打开/关闭要使用的操作符。

是否可以与Rust中的以下C ++代码相同?可能在同一个文件中?

struct S
{
    int value;
};

namespace first
{
S operator+(S lhs,S rhs)
{
    return S{ lhs.value + rhs.value };
}
}

namespace second
{
S operator+(S lhs,S rhs)
{
    return S{ lhs.value * rhs.value };
}
}

int main()
{
    S s1{5};
    S s2{10};
    {
        using namespace first;
        S s3 = s1 + s2;
        std::cout << s3.value << std::endl;
    }
    {
        using namespace second;
        S s3 = s1 + s2;
        std::cout << s3.value << std::endl;
    }
}

解决方法

是否可以与Rust中的以下C ++代码相同? 可能在同一个源文件中?

不,由于以下原因,它不是(不完全是)

  1. 结构不能两次实现相同的特征(为什么要这么做?)
  2. rust中没有函数重载

关于代码中想要的内容,您可以将其近似如下:


#[derive(Debug)]
struct S(i32);

mod first {
    use crate::S;
    pub trait Foo {
        fn bar(self,s: S) -> S;
    }
    
    impl Foo for S  {
        fn bar(self,s: S) -> S {
            S(self.0 + s.0)
        }
    }
}

mod second {
    use crate::S;
    pub trait Foo {
        fn bar(self,s: S) -> S {
            S(self.0 * s.0)
        }
    }
}

fn main() {
    let first_res = first::Foo::bar(S(1),S(2));
    let second_res = second::Foo::bar(S(1),S(2));

    println!("{:?},{:?}",first_res,second_res);
    
    {
        use first::Foo;
        println!("{:?}",S(1).bar(S(2)));
    }
    
    {
        use second::Foo;
        println!("{:?}",S(1).bar(S(2)));
    }
}

Playground

请注意,Foo特性对于编译器而言确实是不同的特性。因此,您要实现两个不同的特征,而不是一个。出于相同的原因,两种bar方法也不同。

,

Rust的惯用答案:

如何为Type使用+,

是包装类型并在包装器上实现运算符。

playground

上的示例
#[derive(Clone,Copy,Debug)]
struct S(i32);

#[derive(Debug)]
struct Adder(pub S);

impl std::ops::Add<S> for Adder {
    type Output = S;

    fn add(self,other: S) -> S { S(self.0.0 + other.0) }
}

impl std::ops::Add<Adder> for S {
    type Output = S;

    fn add(self,other: Adder) -> S { S(self.0 + other.0.0) }
}

#[derive(Debug)]
struct Multiplier(pub S);

impl std::ops::Add<S> for Multiplier {
    type Output = S;

    fn add(self,other: S) -> S { S(self.0.0 * other.0) }
}

impl std::ops::Add<Multiplier> for S {
    type Output = S;

    fn add(self,other: Multiplier) -> S { S(self.0 * other.0.0) }
}

fn main() {
    let one = S(5);
    let two = S(10);

    println!("{:?}",one + Adder(two));
    println!("{:?}",Adder(one) + two);
    
    println!("{:?}",one + Multiplier(two));
    println!("{:?}",Multiplier(one) + two);
}

这个习惯用法可以在标准库中看到,其中std::num::Wrapping类型可用于包装整数,在这种情况下,加,减和乘运算将重新定义以使用模运算。