代码之家  ›  专栏  ›  技术社区  ›  Magnus Hoff

当无法进行类型推断时,使用泛型特征方法,如.into()

  •  51
  • Magnus Hoff  · 技术社区  · 9 年前

    我希望能够使用 .into() 在无法进行类型推断的上下文中转换值。这通常是当我想将临时值转换为其他类型以将其传递到泛型函数时。有关示例,请参见以下代码( playground ):

    use std::convert::*;
    
    struct NewType(pub i32);
    
    impl From<NewType> for i32 {
        fn from(src: NewType) -> i32 {
            src.0
        }
    }
    
    fn main() {
        let a = NewType(5);
        println!("{}", a.into()); // Understandably won't compile
    }
    

    我得到了错误:

    error[E0282]: type annotations needed
      --> src/main.rs:13:20
       |
    13 |     println!("{}", a.into());
       |                    ^^^^^^^^ cannot infer type for `T`
    

    如何正确地告诉编译器我要转换 a 进入 i32 ?

    我可以通过明确喂食让它正常工作 Into 使用类型参数: Into::<i32>::into(a) .这比我希望能够实现的更加详细和明确,尤其是在我没有导入的情况下 进入 ( std::convert::Into::<i32>::into(a) ). a.into::<i32>() 可以接受,但这不是类型参数的用途。

    a.into() as i32 看起来不错,但这种语法不起作用。

    有没有我错过的把戏?

    5 回复  |  直到 5 年前
        1
  •  42
  •   Shepmaster Tim Diekmann    7 年前

    你可以用 From::from :

    use std::convert::*;
    
    struct NewType(pub i32);
    
    impl From<NewType> for i32 {
        fn from(src: NewType) -> i32 {
            src.0
        }
    }
    
    fn main() {
        let a = NewType(5);
        println!("{}", i32::from(a));
    }
    

    您可以在 docs for the convert module .

        2
  •  37
  •   Shepmaster Tim Diekmann    7 年前

    我认为没有更好的办法了。因为类型参数是在特性上,而不是方法上 into() ,涡轮鱼运营商 into::<i32>() 这不起作用。正如您所说,您可以使用完全限定语法使其工作:

    Into::<i32>::into(a)
    

    注意 Into 再出口 std::prelude ,这意味着您永远不必指定完整路径,因为trait始终在范围内。

    当然,也总是可以将临时对象绑定到名称,并使用 let -绑定:

    let tmp: i32 = a.into();
    

    不过,未来可能会更好!有一个 Type Ascription for Expressions RFC ,已被接受和实施。该功能仍然不稳定,但如果实现了,您可以编写如下内容:

    println!("{}", (a.into(): i32));   // still unstable :/
    
        3
  •  9
  •   Shepmaster Tim Diekmann    7 年前

    显然,这在Rust上是可能的 type ascription ,这似乎是为该用例设计的功能( playground ):

    #![feature(type_ascription)]
    
    use std::convert::*;
    
    struct NewType(pub i32);
    
    impl From<NewType> for i32 {
        fn from(src: NewType) -> i32 {
            src.0
        }
    }
    
    fn main() {
        let a = NewType(5);
        println!("{}", a.into(): i32);
    }
    

    由于这在一个实验特性中可用,因此可以合理地得出结论,否则它在语言本身中缺失。

        4
  •  0
  •   Matthieu M.    9 年前

    您可以通过将结果赋给变量来简单地注释结果的类型。

    let b: i32 = a.into();
    println!("{}", b);
    
        5
  •  -2
  •   Shepmaster Tim Diekmann    4 年前

    您可以将函数定义隐藏在某个地方,以使其余代码看起来更漂亮。

    use std::convert::*;
    
    struct NewType(pub i32);
    
    impl From<NewType> for i32 {
        fn from(src: NewType) -> i32 {
            src.0
        }
    }
    
    fn main() {
        let a = NewType(5);
        println!("{}", a.get_i32());
    }
    
    mod r#impl {
        impl super::NewType {
            pub fn get_i32(self) -> i32 {
                self.into()
            }
        }
    }
    
    推荐文章