簡體   English   中英

Mismatched types parameter error on rust generics

[英]Mismatched types parameter error on rust generics

expected type parameter T , found type parameter A錯誤顯示。 我也寫了終生實現代碼,但它仍然沒有解決問題。 我做錯了什么?

fn main() {
    let x = 3;
    let y = 5.0;
    let max_value = max(x, y);
    println!("The maximum value is {}", max_value); 
}

fn max<T: PartialOrd, A: PartialOrd>(x: T, y: A) -> T {
    if x > y {
        x
    } else {
        y
    }
}

// fn main() {
//     let x = 3;
//     let y = 5.0;
//     let max_value = max(&x, &y);
//     println!("The maximum value is {}", max_value); 
// }

// fn max<'a, T: PartialOrd + Copy, A: PartialOrd + Copy>(x: &'a T, y: &'a A) -> &'a T {
//     if x > y {
//         x
//     } else {
//         y
//     }
// }

TA不必是同一類型,所以你有兩個問題。

首先是您將TA限制為PartialOrd ,這與PartialOrd<Self>相同。 所以你的實際約束是T: PartialOrd<T>, A: PartialOrd<A> 這意味着您可以比較T與其他T的順序以及A與其他A的順序,但是x > yTA進行比較。

相反,您需要約束T: PartialOrd<A> (這也失敗了,但由於main()中的調用——稍后會詳細介紹。)

其次,聲明 function 返回Telse塊返回y ,這不是T Rust 是靜態類型的,因此它期望類型完全匹配。

這可以通過要求A可以轉換為T (即A: Into<T> )來解決,然后您可以從else塊返回y.into()

所以在這一點上,我們有:

fn main() {
    let x = 3;
    let y = 5.0;
    let max_value = max(x, y);
    println!("The maximum value is {}", max_value); 
}

fn max<T: PartialOrd<A>, A: Into<T>>(x: T, y: A) -> T {
    if x > y {
        x
    } else {
        y.into()
    }
}

但是現在您遇到了更多問題:

  • 沒有滿足T: PartialOrd<A>的類型TA ,其中T是一個 integer, A是一個浮點數,因此您不能像在main()中那樣用35.0調用這個 function。
  • 同樣,沒有針對 integer 類型T和浮點類型A AInto<T>的實現。
  • x > y移動xy ,然后您不能稍后返回它們。 這可以通過將TA都限制為Copy來輕松解決。

第二個問題可以通過使用一個表示“ TA ”的枚舉並返回它來解決。 either crate有一個名為Either的類型,我們可以在這里將其用作Either<T, A>

use either::Either;

fn main() {
    let x = 3;
    let y = 5.0;
    let max_value = max(x, y);
    println!("The maximum value is {}", max_value); 
}

fn max<T: PartialOrd<A> + Copy, A: Copy>(x: T, y: A) -> Either<T, A> {
    if x > y {
        Either::Left(x)
    } else {
        Either::Right(y)
    }
}

println!起作用是因為Either<T, A>TA都實現時實現了Display 。)

您仍然會遇到整數和浮點數之間沒有內置排序實現的問題。

“萬歲”解決方案可能是要求TA都可以轉換為f64 ,然后在比較它們之前將xy轉換為f64

use either::Either;

fn main() {
    let x = 3;
    let y = 5.0;
    let max_value = max(x, y);
    println!("The maximum value is {}", max_value); 
}

fn max<T: Copy + Into<f64>, A: Copy + Into<f64>>(x: T, y: A) -> Either<T, A> {
    if x.into() > y.into() {
        Either::Left(x)
    } else {
        Either::Right(y)
    }
}

這是我們實際編譯的第一段代碼,這可能足以滿足您的目的。 但是,仍然存在一些問題:

  • i64u64不能無損轉換為f64 ,因此它們沒有實現Into<f64> ,所以如果你改變let x = 3; let x = 3u64; (或3i64 )編譯將再次失敗。
  • f64不實現Ord ,因為可能有兩個f64xy不相等但都不大於另一個 - 例如,如果其中一個值為NaN 這不會導致您的程序崩潰,但它可能會產生意外或不正確的結果。

我懷疑這是一個學習練習,所以希望這個答案可以幫助您理解原始代碼有什么問題。 我不會在實際程序中推薦這樣的 function; 相反,最好將兩個 arguments 提前轉換為相同的Ord實現類型,然后您可以使用內置的std::cmp::max function (或Ord::max )。

暫無
暫無

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

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