Rust 中的多个运算符重载
More than one operator overload in Rust
我知道可以通过使用 traits 在 Rust 中实现运算符重载。在 C++ 中,也可以对同一个运算符和相同的 struct
进行多个运算符重载,并切换 on/off 使用哪个运算符。
是否可以在 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;
}
}
Is it possible to do the same as the following C++ code in Rust?
Possibly in the same source file?
不,不是(不完全是),原因如下:
- 一个结构不能实现相同的特征两次(你为什么要那样?)
- 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;
}
impl Foo for S {
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)));
}
}
请注意,Foo
特性对于编译器来说确实是不同的特性。所以你正在实现两个不同的特征,而不是一个。出于同样的原因,两种bar
方法也是不同的。
Rust 中的惯用答案:
How do I use different overloads of +, <, ... for my Type?
就是把类型包装起来,在包装器上实现运算符。
上的示例
#[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
类型可用于包装整数,在这种情况下,加法、减法和乘法是 re-defined 以使用模运算。
我知道可以通过使用 traits 在 Rust 中实现运算符重载。在 C++ 中,也可以对同一个运算符和相同的 struct
进行多个运算符重载,并切换 on/off 使用哪个运算符。
是否可以在 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;
}
}
Is it possible to do the same as the following C++ code in Rust? Possibly in the same source file?
不,不是(不完全是),原因如下:
- 一个结构不能实现相同的特征两次(你为什么要那样?)
- 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;
}
impl Foo for S {
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)));
}
}
请注意,Foo
特性对于编译器来说确实是不同的特性。所以你正在实现两个不同的特征,而不是一个。出于同样的原因,两种bar
方法也是不同的。
Rust 中的惯用答案:
How do I use different overloads of +, <, ... for my Type?
就是把类型包装起来,在包装器上实现运算符。
上的示例#[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
类型可用于包装整数,在这种情况下,加法、减法和乘法是 re-defined 以使用模运算。