【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>
where
    T: 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> where
    I: 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 where
    I: 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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值