types - 具有特征 : Differences of specifying an explicit lifetime bound? 的类型定义

标签 types rust traits

当我在类型定义中使用特征时,我在理解生命周期限制要求时遇到了问题。例如:

trait Kind { /* ... */ }
type CollectionOfKind<'a> = Vec<&'a Kind>;
// => error: explicit lifetime bound required

已经针对结构中的特征( Answer 1 , Answer 2 )讨论了生命周期限制的要求。起初,我根本无法在这里应用“添加生命周期”的方法,因为这是行不通的:

type CollectionOfKind<'a> = Vec<&'a Kind + 'a>;
type CollectionOfKind<'a> = Vec<&'a Kind + 'static>;

然而,这只是一个语法问题,因为 precedence of plus正如@Shepmaster 所指出的。

总的来说,我现在找到了三种指定生命周期边界的方法:

// Version 1: Adding 'static to the trait itself
trait Kind : 'static { /* ... */ }
type CollectionOfKind<'a> = Vec<&'a Kind>;
// Version 2: Adding 'static to the type definition
trait Kind { /* ... */ }
type CollectionOfKind<'a> = Vec<&'a (Kind + 'static)>;
// Version 3: Adding the lifetime of the reference to the trait object (?)
trait Kind { /* ... */ }
type CollectionOfKind<'a> = Vec<&'a (Kind + 'a)>;

我不明白的是:这三种情况之间的确切区别是什么?

我的问题:

为了看到差异,我试图理解其他答案中提到的某些要点。例如在上面链接的答案 2 中,我发现了以下我不完全理解的提示:

In this case, the 'static requires that the underlying object must be a real struct, or a &'static reference, but other references won't be allowed.

底层对象必须是“真实”结构是什么意思?结构如何在不“真实”的情况下实现特征?

与@Shepmaster 引用的引述类似:

You have to specify the lifetime two times: once for the lifetime of the reference, and once for the trait object itself, because traits can be implemented for references, and if the underlying object is a reference, you must specify its lifetime as well.

老实说,我不明白为什么必须指定两次。我虽然通过引用实现特定特征的对象来定义特征对象。所以根据定义(?)它是一个引用,因此无论如何都有一个生命周期?

最佳答案

新问题的答案

你真的有two orthogonal cases .我将首先解决更简单的问题,即#2 和#3 的区别。评论与我希望的代表性示例一致:

trait Kind { 
    fn trait_fn(&self) -> u8 { 0 }
}

type CollectionOfKind1<'a> = Vec<&'a (dyn Kind + 'static)>;
type CollectionOfKind2<'a> = Vec<&'a (dyn Kind + 'a)>;

struct Alpha;
impl Kind for Alpha {}

struct Beta<'b> {
    name: &'b str,
}
impl<'a> Kind for Beta<'a> {}

fn main() {
    let name = "world".to_string();

    // Doesn't need/have it's own lifetime.
    let a = Alpha;
    // Has a reference to something with the 'static lifetime.
    let b1 = Beta { name: "hello" };
    // Has a reference to something with the lifetime of `name`,
    // which is less than 'static.
    let b2 = Beta { name: &name[..] };  

    // Our vector is composed of references to
    // things that *might* have a reference themselves!
    let mut c1: CollectionOfKind1 = Vec::new();
    c1.push(&a);
    c1.push(&b1);
    // c1.push(&b2); // error: `name` does not live long enough
    
    let mut c2: CollectionOfKind2 = Vec::new();
    c2.push(&a);
    c2.push(&b1);
    c2.push(&b2); // Hooray
}

这里需要注意的是,生命周期不必相同!你可以这样写:

type CollectionOfKind2<'a, 'b> = Vec<&'a (dyn Kind + 'b)>;

第二件事是 trait Foo : 'static 的含义。我不太确定,但我写了这个小例子:

trait Foo : 'static {}

fn x(a: &Foo) {}

fn main() {
    x(&3u8);
}

编译时出现此错误

the trait Foo must be implemented for the cast to the object type Foo + 'static

基于此,我认为 Foo : 'static 只是 Foo + 'static 的另一种写法。我能想到的主要区别是它限制了 ever 在具有非 'static 生命周期的结构上实现的特征:

struct B<'a> {
    b: &'a str,
}

impl<'a> Foo for B<'a> {}

有错误

declared lifetime bound not satisfied [...] but lifetime parameter must outlive the static lifetime

原始答案

我看到您已经发现了这一点,但您可能想要更新您的 Rust 版本。如果我在 Playpen 上编译你的代码,我会得到关于如何修复它的建议:

error: expected a path on the left-hand side of `+`, not `&'a Kind` [E0178]
type CollectionOfKind<'a> = Vec<&'a Kind + 'a>;
                                ^~~~~~~~
note: perhaps you meant `&'a (Kind + 'a)`? (per RFC 438)
type CollectionOfKind<'a> = Vec<&'a Kind + 'a>;
                                ^~~~~~~~

引用 RFC 438, Precedence of Plus .

关于types - 具有特征 : Differences of specifying an explicit lifetime bound? 的类型定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27675554/

相关文章:

generics - 难以理解 Rust 中的特征和泛型

c++ - 特性实例作为不同特征的模板参数

scala - spray-json:序列化一个通用特征

rust - 我的 C FFI 中的 f64 应该使用哪种 C 类型?

rust - 使用借用的结构字段导出 `Deserialize`

haskell - 将数字限制在一个范围内(Haskell)

haskell - 无类型 lambda 演算的冒险

python -numpy : read csv into numpy with proper value type

Scala 类型参数在各个地方

struct - 如何在结构之前的一个文档 block 中记录 Rust 结构/枚举?