繁体   English   中英

如何在 Rust 中使用具有 `impl trait` 返回类型的 `Fn` trait?

[英]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_whitespacestr::split_ascii_whitespace有不同的返回类型。 您不能构造不同类型的数组。 相反,您可以创建一组装箱的特征对象 这将执行动态调度,其中调用的特定方法在运行时确定(而不是静态调度,静态调度在编译时已知特定方法版本)

本质上,目标是让所有函数的签名为:

for<'a> fn(&'a str) -> Box<dyn Iterator<Item=&'a str> + 'a>

这是一个函数,它接受一个&str并返回一些在运行时确定的&str的迭代器。

现在,这就是它开始变得混乱的地方,我希望有人可以提出更好的方法来做到这一点。

str::split_whitespace工作的一种方法是围绕str::split_whitespacestr::split_ascii_whitespace创建包装函数来返回一个装箱的特征,而不是它们各自的SplitWhitespaceSplitAsciiWhitespace结构。 我使用了一个辅助宏来简单地将函数调用的返回值包装在一个 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM