从内部称为通用函数的特征

时间:2016-05-21 15:12:48

标签: rust

我使用From特征将i32转换为我自己的结构。我在一个不编译的泛型函数do_stuff中使用此转换:

use std::convert::*;

struct StoredValue {
    val: i32,
}

impl From<i32> for StoredValue {
    fn from(value: i32) -> StoredValue {
        return StoredValue {val: value};
    }
}

/// Generic function that stores a value and do stuff
fn do_stuff<T>(value: T) -> i32 where T: From<T> {
    let result = StoredValue::from(value);
    // .... do stuff and
    return 0;
}

fn main () {
    let result = do_stuff(0); // call with explicit type
}

和编译错误:

main.rs:15:18: 15:35 error: the trait `core::convert::From<T>` is not implemented for the type `StoredValue` [E0277]
main.rs:15     let result = StoredValue::from(value);

From<T>实现StoredValue的通用版本是否有意义?

2 个答案:

答案 0 :(得分:2)

你的泛型函数说,“我接受任何实现自己创建的类型。”这不是你想要的。

可以想要说些什么:

“我接受任何可以转换为i32的类型,以便我可以创建StoredValue。”这是有效的,因为您知道StoredValue实现了From<i32>

fn do_stuff<T>(value: T) -> i32 where T: Into<i32> {
    let result = StoredValue::from(value.into());
    // ...
}

或者,“我接受任何可以将转换为 a StoredValue的类型。”有一个方便的特征与From<T>特征一起,它被称为Into<T>

fn do_stuff<T>(value: T) -> i32 where T: Into<StoredValue> {
    let result = value.into();
    // ...
}

记住如何/何时使用这两个特征的方法是:

  • 当您知道最终结果是什么时,请使用Into<T>,即来自?->T
  • 当您知道必须从什么开始时使用From<T>,而不是最终结果,即T->?

这两个特征可以齐头并进的原因是,如果你有一个T来实现Into<U>,你有V来实现From<U>你可以来自T->U->V

Rust std lib已经进行了这样的转换,其中说“实现T的任何类型From<U>,而不是U实现Into<T>。”

因此,当您实施From<i32> for StoredValue时,您可以假设有Into<StoredValue> for i32

答案 1 :(得分:1)

要使do_stuff()有效,必须可以将T类型转换为StoredValue。所以它的声明应该是

fn do_stuff<T>(value: T) -> i32 where StoredValue: From<T> {

编辑:我同意Shepmaster认为最好

fn do_stuff<T>(value: T) -> i32 where T: Into<StoredValue> {
    let result = value.into();
    // ...

由于存在将T: From<U>转换为U: Into<T>的通用实现,因此允许使用两种类型的转换,即实现From的转换和实现Into的转换。在我的第一个版本中,只有实现From的转化才有效。