27

Box<Fn() + Send + 'static>生锈是什么意思?

我在阅读高级类型章节时偶然发现了这种语法。Send是一个特征,但是对于类型参数化中的特征(在这种情况下)来说,这对+一生意味着什么?'static又是什么Fn()

4

2 回答 2

44

让我们一一分解。

盒子

Box<T>是指向堆分配的指针T。我们在这里使用它是因为 trait 对象只能存在于指针之后。

特征对象

Box<Fn() + Send + 'static>,Fn() + Send + 'static是一个特征对象类型。以后会Box<dyn (Fn() + Send + 'static)>出来避免混淆。

里面dyn是对原始类型的限制。Box<T>只有Box<Fn() + Send + 'static>T: Fn() + Send + 'static. 因此,虽然我们不知道原始类型,但我们可以假设它是并且Fn()Send生命周期'static

Fn()

这是一个特征,就像Cloneor一样Default。但是,它使用了一种特殊的语法糖

  • Fn(A1, ..., An)是 . 的语法糖Fn<(A1, ..., An), Output=()>
  • Fn(A1, ..., An) -> R是 . 的语法糖Fn<(A1, ..., An), Output=R>
  • 此语法糖也适用于以下特征:FnFnMutFnOnceFnBox.

那么是什么Fn意思呢?T: Fn(A1, ..., An) -> Rmeanx: T是一个带有参数A1, ..., An和返回类型的可调用对象R。示例包括函数指针和闭包。

发送

Send意味着这种类型的值可以跨线程发送。由于这是一个自动特征,因此可以将其指定为类型的第二个边界dyn特征对象类型)。

'static边界

事实上,dyn类型(特征对象类型)必须只有一个生命周期限制。省略时推断。推理规则在RFC 0192RFC 1156中描述。基本上如下:

  1. 如果明确给出,则使用该生命周期。
  2. 否则,它是从内在特征推断出来的。例如,Box<Any>Box<Any + 'static>因为Any: 'static
  3. 如果特征没有适当的生命周期,则从外部类型推断。例如,&'a Fn()&'a (Fn() + 'a)
  4. 如果这甚至失败了,它会退回到'static(对于函数签名)或匿名生命周期(对于函数体)。

结论

f: Box<Fn() + Send + 'static>是指向可调用值(原始类型未知且动态更改)的拥有指针,例如闭包(没有参数或没有返回值),它可以跨线程发送并且与程序本身一样长。

于 2017-12-29T06:06:05.910 回答
5

我发现该'static部分需要从最高投票的答案中进行更多详细说明。

底层具体类型表示为A

特征对象Box<dyn Fn() + Send + 'static>可以从 的实例构造A,这意味着A: Fn() + Send + 'static。也就是说,具体类型A是有static生命周期的。

as trait bound的具体解释:'static

作为 trait bound,这意味着该类型不包含任何非静态引用。例如。接收者可以随心所欲地保留该类型,并且在他们丢弃它之前它永远不会变得无效。

重要的是要理解这意味着任何拥有的数据总是通过'static生命周期的限制,但对该拥有数据的引用通常不会

对于将任何生命周期用作特征绑定的情况的生成性解释:

T: 'a 意味着 T 的所有生命周期参数都超过了 'a。例如,如果 'a 是一个不受约束的生命周期参数,则 i32: 'static 和 &'static str: 'a 满足但 Vec<&'a ()>: 'static 不满足。

对于我们的例子,所有生命周期参数Amust outlive 'static,例如

pub struct A<'a> {
   buf: &'a[u8]
}

达不到要求A: 'static

于 2021-04-27T03:19:19.223 回答