簡體   English   中英

在結構中使用泛型並通過特征實現

[英]Using a generic in a struct and implementing via a trait

我有這樣定義的結構

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

我正在嘗試創建一個簡單的特征和實現,它使用這個結構來計算一些簡單的數學。

我的 trait 和 impls 看起來像這樣

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();
}

當我把它放到 Rust 的操場上時,編譯失敗,因為Mul沒有在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> 

我不知道如何在impl Calculate<T>T實現Mul

我想要實現的是我可以發送f32i32 ,而無需創建兩個不同的 impl 定義,因此只需傳入T

此語法不正確:

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塊沒有意義; 您不太可能想要為特征實現函數,並且您不會在后者中提供Shape 該 trait 也不使用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不能在沒有強制轉換的情況下乘以任何整數值。

來自 num crate 的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());
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM