pub fn understand_lifetime_hrtb()
Expand description
示例: 理解 trait对象中的生命周期参数
trait Foo<'a> {}
struct FooImpl<'a> {
s: &'a [u32],
}
impl<'a> Foo<'a> for FooImpl<'a> {
}
// 为 trait对象 增加 'a ,因为 Box 默认是 static 的,而FooImpl 中的 s 则是引用
// 表明该trait对象(结构体实例)与其结构体中的引用的生命周期是一样长的(<=)
fn foo<'a>(s: &'a [u32]) -> Box<dyn Foo<'a> + 'a> {
Box::new(FooImpl { s: s })
}
fn main(){}
§理解 HRTB (higher ranked trait bounds)
示例一:
use std::fmt::Debug;
trait DoSomething<T> {
fn do_sth(&self, value: T);
}
impl<'a, T: Debug> DoSomething<T> for &'a usize {
fn do_sth(&self, value: T) {
println!("{:?}", value);
}
}
fn foo<'a>(b: Box<DoSomething<&'a usize>>) {
let s: usize = 10;
b.do_sth(&s) // error[E0597]: `s` does not live long enough
}
fn main(){
let x = Box::new(&2usize);
foo(x);
}
修正:使用 for<'f>
改为 late bound
use std::fmt::Debug;
trait DoSomething<T> {
fn do_sth(&self, value: T);
}
impl<'a, T: Debug> DoSomething<T> for &'a usize {
fn do_sth(&self, value: T) {
println!("{:?}", value);
}
}
fn bar(b: Box<for<'f> DoSomething<&'f usize>>) {
let s: usize = 10;
b.do_sth(&s);
}
fn main(){
let x = Box::new(&2usize);
bar(x);
}
示例 2:
use rand;
use std::io::Read;
trait Checksum<R: Read> {
fn calc(&mut self, r: R) -> Vec<u8>;
}
struct Xor;
impl<R: Read> Checksum<R> for Xor {
fn calc(&mut self, mut r: R) -> Vec<u8> {
let mut res: u8 = 0;
let mut buf = [0u8; 8];
loop {
let read = r.read(&mut buf).unwrap();
if read == 0 {
break;
}
for b in &buf[..read] {
res ^= b;
}
}
vec![res]
}
}
struct Add;
impl<R: Read> Checksum<R> for Add {
fn calc(&mut self, mut r: R) -> Vec<u8> {
let mut res: u8 = 0;
let mut buf = [0u8; 8];
loop {
let read = r.read(&mut buf).unwrap();
if read == 0 {
break;
}
for b in &buf[..read] {
let tmp = res as u16 + *b as u16;
res = tmp as u8;
}
}
vec![res]
}
}
fn main() {
let mut buf = [0u8; 8];
// error[E0308]: `if` and `else` have incompatible types
// 修正:
// step 1: Box<dyn Checksum<&[u8]>> 转为 trait 对象
// step 2: Box<dyn for<'a> Checksum<&'a [u8]>> 使用 for<'a> 转为 late bound
let mut checker = if rand::random() {
println!("Initializing Xor Checksum");
Box::new(Xor)
} else {
println!("Initializing Add Checksum");
Box::new(Add)
};
let mut data = "Sedm lumpu slohlo pumpu za uplnku".as_bytes();
let mut i = 0;
loop {
let chunk_size = data.read(&mut buf).unwrap();
if chunk_size == 0 {
break;
}
let cs = checker.calc(&buf[..chunk_size]);
println!("Checksum {} is {:?}", i, cs);
i += 1;
}
}