我希望能够使用 .into()
在不可能推理的上下文中转换一个值。这通常是当我想将临时值转换为其他类型以将其传递到通用函数时。请参阅以下代码以获取示例(游乐场):
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::<i32>::into(a)
)明确喂食Into
来使其正常工作。这比我希望能够实现的更详细和明确,尤其是在我没有导入Into
(std::convert::Into::<i32>::into(a)
)的情况下。a.into::<i32>()
是可以接受的,但这不是类型参数所在的地方。
a.into() as i32
看起来不错,但是这种确切的语法不起作用。
我缺少一个技巧吗?
您可以使用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));
}
您可以在convert
模块的文档中阅读有关它的更多信息。
我认为没有更好的方法。由于类型参数在性状上,而不是方法into()
,因此涡轮FAMECON into::<i32>()
不起作用。正如您所说,您可以使用完整的syntax来使其正常工作:
Into::<i32>::into(a)
请注意,Into
在std::prelude
中重新效仿,这意味着您永远不必指定完整的路径,因为特征始终处于范围内。
当然,也总是有可能将您的临时性绑定到名称并使用let
-结合的类型注释:
let tmp: i32 = a.into();
不过,将来可能会更好!有一个已经接受和实施的表达式 rfc的类型。该功能仍然不稳定,但是如果实现了,则可以写出类似的内容:
println!("{}", (a.into(): i32)); // still unstable :/
显然,这在rust nightly with type castription中可能是可能的,这似乎是为此用例设计的功能(游乐场):
#![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);
}
由于这在实验功能中可用,因此可以合理地得出结论,否则该语言中缺少了适当的语言。
您可以通过将结果分配给变量来简单地注释结果的类型。
let b: i32 = a.into();
println!("{}", b);
您可以将函数定义隐藏在某个地方以获取其余代码看起来不错。
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()
}
}
}