我有一个类似type SomeSub = dyn for<'a> Fn(&'a str) -> &'a str;的FN特征的类型别名,我想将其与具有明确生命周期的Box一起使用,例如Box<SomeSub + 'b>.不幸的是,这不能编译:

type SomeSub = dyn for<'a> Fn(&'a str) -> &'a str;

struct SomeBuilder(pub usize);

impl SomeBuilder {
    // --> this gets rejected with "type aliases cannot be used as traits"
    fn get_closure<'o>(
        &'o self
    ) -> Box<dyn SomeSub + 'o> {
        Box::new(|s| &s[self.0..])
    }

    // This works, but duplicates the code of the type alias
    fn get_closure_long<'o>(
        &'o self
    ) -> Box<dyn for<'a> Fn(&'a str) -> &'a str + 'o> {
        Box::new(|s| &s[self.0..])
    }
}

当第二个方法get_closure_long()编译时,get_closure()导致错误:

error[E0404]: expected trait, found type alias `SomeSub`
 --> src/lib.rs:8:18
  |
8 |     ) -> Box<dyn SomeSub + 'o> {
  |                  ^^^^^^^ type aliases cannot be used as traits

省略dyn个,比如-> Box<SomeSub + 'o>,将被拒绝,理由是"类型别名不能用作特征".使用Box<SomeSub> Works bot不允许闭包捕获任何引用.

将闭包类型别名与Box以及该Box的显式生存期相结合的正确方法是什么?

推荐答案

您可以将类型别名设置为泛型:

type SomeSub<'b> = dyn for<'a> Fn(&'a str) -> &'a str + 'b;

SomeSub<'o>是包含生存期的有效类型,因此编译如下:

fn get_closure<'o>(&'o self) -> Box<SomeSub<'o>> {
    Box::new(|s| &s[self.0..])
}

Playground

或者,您可以使用如图in this answer所示的技术来模拟特性别名:

trait SomeSub: for<'a> Fn(&'a str) -> &'a str {}

impl<T> SomeSub for T where T: for<'a> Fn(&'a str) -> &'a str {}

然后编译返回Box<dyn SomeSub + 'o>的原始get_closure().

Playground

Rust相关问答推荐

什么是谓词的简短和简洁类型

PyReadonlyArray2到Vec T<>

为什么我的梅森素数代码的指数越大,速度就越快?

如何使用syn插入 comments ?

通过解引用将值移出Box(以及它被脱糖到什么地方)?

如何为rust trait边界指定多种可能性

我如何制作一个变异迭代器来锁定内部数据直到删除?

为什么Rust不支持带关联常量的特征对象?

要求类型参数有特定的大小?

为什么切片时需要参考?

在 Rust 中忽略 None 值的正确样式

如何在 Rust 中显式声明 std::str::Matches<'a, P> ?

由特征键控的不同 struct 的集合

Rust 函数指针似乎被borrow 判断器视为有状态的

Rust 中函数的类型同义词

如何在 Rust 中返回通用 struct

如何在 Rust 中编写修改 struct 的函数

如何在 C++ 和 Rust 之间共享 pthread 同步原语?

Rust 中的通用 From 实现

提取 struct 生成宏中字段出现的索引