本文主要是介绍【Rust每周一知】一种奇怪的表示 T::Item,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
我们都知道,Rust有一种叫 完全限定语法(fully-qualified syntax) 的东西。请看下面的例子:
trait AAA {type Item;fn test();
}struct Foo;impl AAA for Foo {type Item = String;fn test() {println!("a test.");}
}fn main() {let f: Foo::Item= String::from("test foo");println!("{}", f);
}
编译,会提示如下错误:
error[E0223]: ambiguous associated type--> src/main1.rs:20:12|
20 | let f: Foo::Item= String::from("test foo");| ^^^^^^^^^ help: use fully-qualified syntax: `<Foo as Trait>::Item`
应该写成:
let f: <Foo as AAA>::Item= String::from("test foo");
就可以编译通过了,这就是所谓:完全限定语法。
但是,在阅读一些工程的代码的时候,可以发现一种不寻常的用法。我设计了一个例子如下:
trait AAA {type Item0;fn test();
}impl<T> AAA for T {type Item0 = String;fn test() {println!("test it");}
}trait BBB {type Item1;fn doit(&self);
}struct Foo<T> {foo: T
}impl<T> BBB for Foo<T>
whereT: AAA
{type Item1 = T::Item0;fn doit(&self) {println!("just do it.");}
}fn main() {let f = Foo::<u8>{foo: 100};f.doit();
}
上面例子中,T::Item0
这个写法,有点超出我们的认知。泛型可以直接引用其 Trait bound 的 associated type 吗?好像是的。本例子能编译通过并顺利运行。
再来看一个稍微复杂一点的例子:
struct Doubler<I> {iter: I,
}impl<I> Iterator for Doubler<I> whereI: Iterator,I::Item: std::ops::Add<Output=I::Item> + Copy,
{type Item = I::Item;fn next(&mut self) -> Option<Self::Item> {match self.iter.next() {None => None,Some(x) => Some(x + x),}}
}fn sum(range: u32) -> u32 {(1..=range).fold(0, |sum, i| sum + i)
}fn sum2<I>(iter: I) -> I::Item whereI: Iterator,I::Item: std::ops::Add<Output=I::Item> + From<u8>,
{iter.fold(From::from(0u8), std::ops::Add::add)
}fn main() {for i in (Doubler{iter: 1..11u32}) {print!("{} ", i);}println!();println!("Sum is {}", (1..11).fold(0, |sum, i| sum + i));println!("Sum is {} using sum helper", sum(10));println!("Sum is {} using sum good helper", sum2(0..11));println!("ALL DONE");
}
上例中的 I::Item
也是这种情况。
其实也并不难理解,只是在第一次遇到的时候,会很奇怪,Rust 怎么会有这种语法。于是设计了例子来验证这个问题。原来还真是可以的。
本文所有示例地址: https://github.com/daogangtang/learn-rust/tree/master/04generic_with_associated_type
这篇关于【Rust每周一知】一种奇怪的表示 T::Item的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!