rust-quiz:011-function-pointer-comparison.rs
题目
fn f<'a>() {}
fn g<'a: 'a>() {}
fn main() {
let pf = f::<'static> as fn();
let pg = g::<'static> as fn();
print!("{}", pf == pg);
}
关键
数据限定
我们经常使用let a: u32
这种办法去限定一个数据的类型,这算是数据的限定。类型限定
A:T
这种形式,就是类型限定,它决定了一个类型的最基础要求。
当然,也有T
的无要求数据类型。生命周期
lifetime
算是数据还是类型呢,它是一种特殊的数据类型。
它可以被省略,被自动推导;也可以手动声明,还可以手动限定。
展示
生命周期本身是可以自动推导的。
fn f<'b, 'a:'b>(a: &'a u32) -> &'b u32 {
a
}
这里出现了限定,更简略一些
fn f<'a>(a: &'a u32) -> &'a u32 {
a
}
但是,这里最简应该是
fn f(a: &u32) -> &u32 {
a
}
简单总结出来,输出的引用的生命周期始终是受限于输入的生命周期。
但是输入的生命周期是上下文就可以进行推导出来的,某些场景下无需手动声明。
就算手动声明,如果和推导的结果一致,也无大用处。
关键在于:怎么声明,才和推导的不一样?
最关键的一处在于:推导的入参生命周期来源于上下文,我们是可以重新指定的。
- 生命周期在函数签名之外声明
- 生命周期参数以它必须超过的其他生命周期为界
这叫做early bound
,也就是说,无非等到自动推导,提前指定了生命周期。
审题
fn f<'a>() {}
如果方法有生命周期,这里只不过是显式写了出来,并没有额外的操作。fn g<'a: 'a>() {}
这里限定了一个声明周期,也就是运行时需要指定一个声明周期。
fn main() {
let pf = f::<'static> as fn();
let pg = g::<'static> as fn();
print!("{}", pf == pg);
}
因此,pf
其实本身并不能通过编译,因为它并没有实现early bound
的语法。
不能够以指定生命周期的形式进行调用。
而pg
没有问题,因为声明当中,它的生命周期有明显的受限声明。
答案
error
,shit!
改动一下展示的例子,展示”受限”,这和我们平时的类型限定没有什么区别
fn f<'a:'a>(a: &'a u32) -> &'a u32 {
a
}
fn main() {
f::<'static>(&1);
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: