Rust 如何在关联类型中指定生存期参数?

Rust 如何在关联类型中指定生存期参数?,rust,lifetime,Rust,Lifetime,我有这样的特点和简单的结构: use std::path::{Path, PathBuf}; trait Foo { type Item: AsRef<Path>; type Iter: Iterator<Item = Self::Item>; fn get(&self) -> Self::Iter; } struct Bar { v: Vec<PathBuf>, } 但是我得到了这个错误: 错误[E010

我有这样的特点和简单的结构:

use std::path::{Path, PathBuf};

trait Foo {
    type Item: AsRef<Path>;
    type Iter: Iterator<Item = Self::Item>;

    fn get(&self) -> Self::Iter;
}

struct Bar {
    v: Vec<PathBuf>,
}
但是我得到了这个错误:

错误[E0106]:缺少生存期说明符
-->src/main.rs:16:17
|
16型Iter=std::slice::Iter;
|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^预期的生存期参数
我找不到在关联类型中指定生存期的方法。我特别想表示迭代器不能超过
self
生命周期

我必须如何修改
Foo
trait或
Bar
trait实现才能实现这一点


您的问题有两种解决方案。让我们从最简单的一个开始:

给你的性格加上一辈子 问题是
fooget
函数不知道
t
实际上是一个
&Bar
。调用
get
函数时,实际上是移出
foo
变量。您不需要移出对象,只需移动引用即可。如果
fooget
函数尝试调用
get
两次,该函数将无法编译

如果希望
fooget
函数仅接受实现了
Foo
特性以供引用的参数,则需要显式声明此绑定:

fn fooget_twice<'a, T>(foo: &'a T)
where
    &'a T: Foo,
{}
但这还不够聪明


对于更复杂的情况,您可以使用尚未实现的生锈特性:(GATs)。这方面的工作正在被追踪。

将来,你将成为一个终生的
'a
,但Rust还不支持这一点。请参见使用包装器类型 如果trait及其所有实现都在一个板条箱中定义,那么助手类型可能很有用:

trait Foo{
fn get IterableFoo(酒吧和酒吧);
对于实现
Foo
的具体类型,在
IterableFoo
上实现迭代器转换:

impl Foo for Bar{}
恳求{
类型Item=&'a PathBuf;
输入Iter=std::slice::Iter IterableFoo(foo:&'at)
哪里
T:Foo,
&'a T::Iterable:IntoIterator,

我选择使用第一种解决方案,因为从
fooget
类函数的角度来看,它似乎施加的负担更小。第二种解决方案的特点也更为明确。有两种以上的解决方案。另一种解决方案没有这两种方案的缺点,尽管有其自身的缺点。您好,do您知道如何在第二种方法中引用关联的类型
T::Item
,其中
T
不实现
Foo
,仅
&'a T:Foo
?编辑:我找到了它!这是一个有趣的解决方案,
:Item
,但在我看来,只有在同一个板条箱中定义IterableFoo和Bar时,它才能工作,right?所以你不能把它用在你的板条箱定义的通用特性中,你的板条箱的用户将在他们自己的板条箱中实现……或者我遗漏了什么?@Pierre Antoine我添加了另一个允许非板条箱实现的解决方案。
trait Foo<'a> {
    type Item: AsRef<Path>;
    type Iter: Iterator<Item = Self::Item>;
    
    fn get(&'a self) -> Self::Iter;
}
impl<'a> Foo<'a> for Bar {
    type Item = &'a PathBuf;
    type Iter = std::slice::Iter<'a, PathBuf>;
    
    fn get(&'a self) -> Self::Iter {
        self.v.iter()
    }
}
fn fooget<'a, T: Foo<'a>>(foo: &'a T) {}
trait Foo {
    type Item: AsRef<Path>;
    type Iter: Iterator<Item = Self::Item>;
    
    fn get(self) -> Self::Iter;
}

impl<'a> Foo for &'a Bar {
    type Item = &'a PathBuf;
    type Iter = std::slice::Iter<'a, PathBuf>;
    
    fn get(self) -> Self::Iter {
        self.v.iter()
    }
}
fn fooget<T: Foo>(foo: T) {}
fn fooget_twice<'a, T>(foo: &'a T)
where
    &'a T: Foo,
{}
fn fooget_twice<T>(foo: &T)
where
    &T: Foo,
{}