本文介绍了转换为泛型类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个关于 Rust(1.0 版)泛型的新手问题.

I have a newbie question about generics in Rust (version 1.0).

假设我编写了一个通用函数来进行除法.别介意这种功能的用处;使这个问题保持简单是一个简单的功能.

Let's say I write a generic function to do division. Never mind the usefulness of such a function; it's a simple function to keep this question simple.

fn divide<T: std::ops::Div>(a: T, b: T) -> T {
    a / b
}

fn main() {
    println!("{}", divide(42, 18))
}

此程序无法编译.

src/main.rs:2:5: 2:10 error: mismatched types:
 expected `T`,
    found `<T as core::ops::Div>::Output`
(expected type parameter,
    found associated type) [E0308]
src/main.rs:2     a / b
                  ^~~~~

我知道编译器错误告诉我除法运算的结果是类型 Output,而不是 T,我看到了 Output输入标准库文档.

I understand that the compiler error is telling me that the result of the division operation is type Output, not T, and I see the Output type in the standard library documentation.

如何从Output 转换为T?我尝试使用 as 进行转换.

How do I convert from Output to T? I try to use as to cast.

fn divide<T: std::ops::Div>(a: T, b: T) -> T {
    (a / b) as T
}

fn main() {
    println!("{}", divide(42, 18))
}

这会导致不同的编译器错误.

This causes a different compiler error.

src/main.rs:2:5: 2:17 error: non-scalar cast: `<T as core::ops::Div>::Output` as `T`
src/main.rs:2     (a / b) as T
                  ^~~~~~~~~~~~

我没有想法来完成这项工作,而且我意识到我对这里的语言缺乏一些基本的了解,但我什至不知道要寻找什么才能完成这项工作.帮助?

I'm out of ideas to make this work, and I realize I lack understanding of something fundamental about the language here, but I don't even know what to look for to make this work. Help?

推荐答案

您只需指定 T::Output 作为函数的返回类型:

You simply have to specify T::Output as the return type of the function:

fn divide<T: std::ops::Div>(a: T, b: T) -> T::Output {
    a / b
}

编辑以添加更多关于为什么不能在函数内进行强制转换的解释

当您在通用函数除法中时,编译器还不知道您可以将 T 转换为 T::Output,因此转换无效.它们是泛型类型,它们可以是任何东西,编译器如何知道您可以从 T 转换为 T::Output ?

When you are IN your generic function divide, the compiler yet doesn't know that you can cast T to T::Output, so the cast is invalid. They are generic types, they can be anything, how the compiler knows that you can cast from T to T::Output ?

a/b 产生类型为 T::Output 的东西,所以在上面的解决方案中没有强制转换,T::Output就是正确的类型.

a / b produces something of type T::Output, so in the solution above there is not cast, T::Output is simply the right type.

使用 std::convert::From 编辑以添加另一个可能的解决方案

最(我认为)通用的实现是当您知道从 T::Output 到 T 的转换是可能的.您可以绑定T 来为T::Output 实现From.这是一个完整的例子:

The most (I think) generic implementation is when you know that the cast from T::Output to T is possible. You can bound T to implement From for T::Output.This is a complete example:

use std::ops::Div;
use std::convert::From;

fn divide<T: Div>(a: T, b: T) -> T
    where T: From<<T as Div>::Output>
{
    T::from(a / b)
}

#[derive(Debug)]
struct Bip(u32);

impl Div for Bip {
    type Output = f32;

    fn div(self, rhs: Bip) -> f32 {
        (self.0 / rhs.0) as f32
    }
}

impl From<f32> for Bip {
    fn from(value: f32) -> Self {
        Bip(value as u32)
    }
}

fn main() {
    println!("{:?}", divide(12, 4));
    println!("{:?}", divide(Bip(12), Bip(4)));
}

这篇关于转换为泛型类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-14 04:11