在结构中使用泛型并通过特征实现

时间:2016-05-03 00:15:33

标签: generics rust

我有像这样定义的结构

trait Calculate<T: Mul<Output = T>> {
    fn calc(&self, Shape: T) -> T;
}

impl<T> Calculate<T> for Shape<T> {
    fn calc(&self, Shape: T) -> T {
        self.line_one * 2 + self.line_two * 2
    }
}

impl Calculate<i32> {
    fn calc(&self) -> i32 {
        self.line_one * 2 + self.line_two * 2
    }
}

fn calc_fn<T: Calculate<i32>>(calculate: T) {
    calculate.calc();
}

我正在尝试创建一个简单的特征和实现,它使用这个结构来计算一些简单的数学。

我的特质和动作看起来像这样

Mul

当我将它放入Rust游乐场时,编译失败,因为impl Calculate<T>中未实现<T>。但是,如果我将<T: Mul<Output = T>>更改为<anon>:14:21: 14:22 error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `:` <anon>:14 impl <T> Calculate<T: Mul<Output = T>> for Shape<T> ,则会收到错误

Mul

我对Timpl Calculate<T>的{​​{1}}实施f32感到茫然。

我想要实现的是我可以发送i32T的代码而无需创建两个不同的impl定义,因此可以传入{{1}}

1 个答案:

答案 0 :(得分:1)

此语法不正确:

impl<T> Calculate<T: Mul<Output = T>> for Shape<T>

你想要

impl<T: Mul<Output = T>> Calculate<T> for Shape<T>

我几乎总是建议使用where子句;我认为它看起来更好,可能有助于防止这种情况:

impl<T> Calculate<T> for Shape<T>
    where T: Mul<Output = T>,

这只会解锁更多错误。您正试图乘以2,这是一个尚未完全确定的整数变量 - 它是u8吗?它是i32吗?限制并不表示T可以乘以2。此外,您尝试将值添加到一起,但无法保证您可以添加T类型。

impl Calculate<i32>calc_fn块并不真正有意义;你不太可能想implement functions for the trait而你不能在后者中提供Shape。该特征也没有使用Shape: T参数(而且Rust使用snake_case变量名称。

  

我想要实现的是我可以发送f32i32的代码而无需创建两个不同的impl定义,因此可以传入T

在这种情况下,它可能会更容易:

trait Calculate<T> {
    fn calc(&self) -> T;
}

impl Calculate<i32> for Shape<i32> {
    fn calc(&self) -> i32 {
        self.line_one * 2 + self.line_two * 2
    }
}

impl Calculate<f32> for Shape<f32> {
    fn calc(&self) -> f32 {
        self.line_one * 2.0 + self.line_two * 2.0
    }
}

请注意,这些等效! f64的浮点文字(2.0)不是整数(2)。

如果必须具有泛型,则需要将文字2转换为类型T或添加T可以乘以某些限制的限制已知尺寸。不幸的是,f64不能在没有强制转换的情况下乘以任何整数值。

来自数字的FromPrimitive特征是关键所在。使类型Copy也使实现更容易。

extern crate num;

use std::ops::{Add, Mul};
use num::FromPrimitive;

struct Shape<T> {
    line_one: T,
    line_two: T,
}

trait Calculate<T> {
    fn calc(&self) -> T;
}

impl<T> Calculate<T> for Shape<T>
    where T: Copy + FromPrimitive + Add<Output = T> + Mul<Output = T>,
{
    fn calc(&self) -> T {
        let two = T::from_u8(2).expect("Unable to create a value of two");
        self.line_one * two + self.line_two * two
    }
}

fn main() {
    let s1 = Shape { line_one: 2, line_two: 3 };
    let s2 = Shape { line_one: 2.0, line_two: 3.0 };

    println!("{}", s1.calc());
    println!("{}", s2.calc());
}