如何在Rust中转换通用原始类型?

4

我想写类似以下内容的东西:

pub struct Point<T> {
    pub x: T,
    pub y: T,
}

impl<T> Point<T> {
    pub fn from<U>(other: Point<U>) -> Point<T> {
        Point {
            x: other.x as T,
            y: other as T,
        }
    }
}

这是不可能的:

error[E0605]: non-primitive cast: `U` as `T`
 --> src/lib.rs:9:16
  |
9 |             x: other.x as T,
  |                ^^^^^^^^^^^^
  |
  = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait

看到如何将泛型T转换为f32,如果我知道它是可能的?,我了解到From特质不能用于i32f32的转换,这正是我最初想要的。

我能想到的最简单的解决方案是编写一个函数,例如:

pub fn float2_from_int2(v: Point<i32>) -> Point<f32> {
   Point::<f32>::new(v.x as f32, v.y as f32)
}

显然,Rust将从i32f32进行转换时没有问题。是否有更好的编写方式?


请注意,您应该使用 self,这样更有意义。 - Stargateur
你能详细说明一下吗?因为我刚要创建Point<T>,所以我还没有self。因此需要使用from<U>作为构造函数。 - B_old
1个回答

3

您可以使用来自numToPrimitive特性
示例(您可以使用AsPrimitive避免Option):

pub struct Point<T> {
    pub x: T,
    pub y: T,
}

impl<T: Copy + 'static> Point<T> {
    pub fn from<U: num::cast::AsPrimitive<T>>(other: Point<U>) -> Point<T> {
        Point {
            x: other.x.as_(),
            y: other.y.as_(),
        }
    }
}

fn do_stuff() {
    let a = Point{x: 0i32, y: 0i32};
    let b = Point::<f32>::from(a);
}

1
NumCastToPrimitive特质中的方法返回一个Option,因为给定的值可能无法表示为目标类型(例如,您不能在u8中保存256)。使用这些方法确实更安全,因为它们可以避免奇怪的情况。AsPrimitive则忽略此问题,因此其行为与as运算符完全相同。 - E net4
也许实现新稳定的 TryFrom 特质是处理 Optional 结果的好方法? - apetranzilla
如何在“From”特质中实现这个呢?就像这样: impl<T, U> From<Point<T>> for Point<U>... - Elembivios

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接