我想测试一些函数的实现。为了干净利落地做,我想将它们的引用放入一个数组中并逐个调用它们。由于最近的语法更改,要执行此操作,您需要首先使用正确的类型签名显式地将函数强制转换为函数引用。由于用于声明函数的语法与其实际类型不同,因此这是一项非常重要的任务。
如何计算出具有非平凡签名的Rust函数的引用类型(例如,它涉及泛型,生命周期,另外的函数等)?
特定的function(我写的)是用签名声明的:
pub fn take_while2<'a,T,F:Fn(&T)->bool >(initial: &'a [T], predicate: F) -> Option<&'a [T]> {...}
答案 0 :(得分:2)
至少你不能使用这个功能。
首先,你不能拥有通用变量。也就是说,x
不能依赖T
。举一个更简单的例子:
fn test<T>(_: &T) { unimplemented!() }
fn main() {
let x: fn(&u8) = test;
}
这是有效的,因为编译器可以推断具体类型T
(在本例中为u8
)。那你为什么不能那样做呢?因为F
。你要求一个闭包类型,闭包类型是匿名;无论你做什么,你都不能说出一个。如果你设法让类型系统推断闭包类型,它只对完全一个特定的闭包有效。与函数非常相似,每个闭包都有自己独特的类型,即使它字面上相同。与函数不同,闭包没有可以使用的公共基类型。
如果不知道你实际想要完成的是什么,很难提出任何建议。然而,要在黑暗中进行刺杀,你可能想尝试类似的东西:
pub fn take_while2<'a,T>(initial: &'a [T], predicate: Box<Fn(&T) -> bool>) -> Option<&'a [T]> { // '
// ...
}
fn main() {
let functions: Vec<for<'a> fn(&'a [u8], Box<Fn(&u8) -> bool>) -> Option<&'a [u8]>> = vec![take_while2]; // '
// ...
}
请注意使用for<'a>
这是一个排名较高的生命周期,它与'a
定义的take_while2
泛型参数具有相同的功能。 另外请注意,此语法 不适用于类型参数。
感谢Shepmaster提醒我您还使用&Fn(&T) -> bool
而不是盒装关闭。这解除了调用者的堆分配要求。
这还需要您将要传递给predicate
的任何闭包。