【问题标题】:How to implement generics in rust when the generic parameter has multiple datatypes?当泛型参数具有多种数据类型时,如何在 rust 中实现泛型?
【发布时间】:2020-08-05 17:30:35
【问题描述】:

我是 Rust 的新手。

我正在尝试在 rust 中实现一个通用函数,但我遇到了问题。我尝试了很多谷歌的例子来获得解决方案,但没有任何效果。请帮帮我。

在下面的代码中,我想为Point 实现add 函数,它可以采用i32 或另一个Point

fn main() {
    println!("Hello world!");
    let mut point = Point::new(1,1);
    point.add::<i32>(&1);
    point.add::<Point>(&point);
}

#[derive(Copy, Clone)]
struct Point {
    pub x: i32,
    pub y: i32,
}

impl Point {
    pub fn new(x: i32, y: i32) -> Point {
        Point {x, y}
    }

    /**
    Pseudocode as i don't know how to write this in rust
    pub fn add<T: Sized || Point>(&mut self, value: &T) {
            if (T is i32) {
                self.x += = value;
                self.y += value;
            } else (T is Point) {
                self.x += value.x;
                self.y += value.y;
            }
        
    }
    */
}

【问题讨论】:

  • 您是否考虑过实施From
  • 这能回答你的问题吗? How can I approximate method overloading?
  • @IInspectable 是的,我试过了,但是在为i32 实现From 后,调用point.add::&lt;Point&gt;(&amp;point); 时出错
  • @E_net4isbeingtargeted,您建议的链接是为i32f32 实现go 方法,但这里我只想为Point 实现。

标签: generics rust


【解决方案1】:

您可以使用 trait 来做到这一点。由于PointCopy,所以也不需要使用引用:

#[derive(Copy, Clone)]
struct Point {
    pub x: i32,
    pub y: i32,
}

impl Point {
    fn new(x: i32, y: i32) -> Point {
        Point { x, y }
    }
}

trait AddToPoint<T> {
    fn add(&mut self, value: T);
}

impl AddToPoint<i32> for Point {
    fn add(&mut self, value: i32) {
        self.x += value;
        self.y += value;
    }
}

impl AddToPoint<Point> for Point {
    fn add(&mut self, value: Point) {
        self.x += value.x;
        self.y += value.y;
    }
}

fn main() {
    println!("Hello world!");
    let mut point = Point::new(1,1);
    point.add(1);
    point.add(point);
}

另一种可能性是通过实现特征std::ops::AddAssign 来使用运算符重载。然后您可以使用+= 运算符为点添加值:

use std::ops::AddAssign;

#[derive(Copy, Clone)]
struct Point {
    pub x: i32,
    pub y: i32,
}

impl Point {
    fn new(x: i32, y: i32) -> Point {
        Point { x, y }
    }
}

impl AddAssign<i32> for Point {
    fn add_assign(&mut self, value: i32) {
        self.x += value;
        self.y += value;
    }
}

impl AddAssign<Point> for Point {
    fn add_assign(&mut self, value: Point) {
        self.x += value.x;
        self.y += value.y;
    }
}

fn main() {
    println!("Hello world!");
    let mut point = Point::new(1,1);
    point += 1;
    point += point;
}

【讨论】:

    【解决方案2】:

    这里是普通函数和通用函数的例子。 结构值 { 值:f64, }

    struct GenVal<T> {
        gen_val: T,
    }
    
    // impl of Val
    impl Val {
        fn value(&self) -> &f64 {
            &self.val
        }
    }
    
    // impl of GenVal for a generic type `T`
    impl<T> GenVal<T> {
        fn value(&self) -> &T {
            &self.gen_val
        }
    }
    
    fn main() {
        let x = Val { val: 3.0 };
        let y = GenVal { gen_val: 3i32 };
    
        println!("{}, {}", x.value(), y.value());
    }
    

    【讨论】:

    • 问题是要求函数重载的道德等价物,即函数 add 可以用 i32 或另一个 Point 调用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多