[英]How to use `Fn` trait with return type of `impl trait` in Rust?
我想使用返回类型为impl Trait
Fn
特征。 例如:
let funcs: [&Fn(&str) -> impl Iterator<Item = &str>] =
[&str::split_whitespace, &str::split_ascii_whitespace];
但是,无法使用以下错误消息编译此代码:
`impl Trait` not allowed outside of function and inherent method return types
我应该怎么做?
除了现在impl Trait
在语法上只能在有限的地方使用这一事实之外,从语义上来说,它只意味着在它的地方会有一个具体的类型。 它不是异构类型或动态调度的许可证。
这可以做到,但它很快变得笨拙:
type StrFn<'a> = &'a dyn Fn(&'static str) -> Box<dyn Iterator<Item = &'static str>>;
fn main() {
let f1: StrFn = &|s: &'static str| Box::new(s.split_whitespace());
let f2: StrFn = &|s: &'static str| Box::new(s.split_ascii_whitespace());
let fs = vec![f1, f2];
fs[0]("rust 2020").for_each(|s| println!("{}", s));
}
也许有更好的方法。
str::split_whitespace
和str::split_ascii_whitespace
有不同的返回类型。 您不能构造不同类型的数组。 相反,您可以创建一组装箱的特征对象。 这将执行动态调度,其中调用的特定方法在运行时确定(而不是静态调度,静态调度在编译时已知特定方法版本)
本质上,目标是让所有函数的签名为:
for<'a> fn(&'a str) -> Box<dyn Iterator<Item=&'a str> + 'a>
这是一个函数,它接受一个&str
并返回一些在运行时确定的&str
的迭代器。
现在,这就是它开始变得混乱的地方,我希望有人可以提出更好的方法来做到这一点。
str::split_whitespace
工作的一种方法是围绕str::split_whitespace
和str::split_ascii_whitespace
创建包装函数来返回一个装箱的特征,而不是它们各自的SplitWhitespace
和SplitAsciiWhitespace
结构。 我使用了一个辅助宏来简单地将函数调用的返回值包装在一个 Box 中
macro_rules! boxed_return {
($fn_new:ident, $fn:path) => {
fn $fn_new<'a>(s: &'a str) -> Box<dyn Iterator<Item=&'a str> + 'a> {
Box::new($fn(s))
}
}
}
boxed_return!(split_whitespace_wrapper, str::split_whitespace);
boxed_return!(split_ascii_whitespace_wrapper, str::split_ascii_whitespace);
然后我们可以简单地创建拆分器函数数组,如下所示
let funcs = [split_whitespace_wrapper, split_ascii_whitespace_wrapper];
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.