如何在关联类型中指定生命周期参数? [英] How do I specify lifetime parameters in an associated type?

查看:116
本文介绍了如何在关联类型中指定生命周期参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我具有这种特征和简单的结构:

I have this trait and simple structure:

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>,
}

我想为Bar实现Foo特性:

impl Foo for Bar {
    type Item = PathBuf;
    type Iter = std::slice::Iter<PathBuf>;

    fn get(&self) -> Self::Iter {
        self.v.iter()
    }
}

但是我遇到此错误:

error[E0106]: missing lifetime specifier
  --> src/main.rs:16:17
   |
16 |     type Iter = std::slice::Iter<PathBuf>;
   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ expected lifetime parameter

我找不到在该关联类型内指定生存期的方法.我特别要表达的是,迭代器不能超过self生存期.

I found no way to specify lifetimes inside that associated type. In particular I want to express that the iterator cannot outlive the self lifetime.

如何修改Foo特征或Bar特征实现以使其起作用?

How do I have to modify the Foo trait, or the Bar trait implementation, to make this work?

铁锈操场

推荐答案

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

There are a two solutions to your problem. Let's start with the simplest one:

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

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

这要求您在使用特征的任何地方注释生命周期.实现特征时,需要执行通用实现:

This requires you to annotate the lifetime everywhere you use the trait. When you implement the trait, you need to do a generic implementation:

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()
    }
}

当您需要为通用参数提供特征时,还需要确保对特征对象的任何引用都具有相同的生存期:

When you require the trait for a generic argument, you also need to make sure that any references to your trait object have the same lifetime:

fn fooget<'a, T: Foo<'a>>(foo: &'a T) {}

实施特征以引用您的类型

代替为您的类型实现特征,而将其实现为对您类型的引用.这种特质永远不需要这样了解一生.

Implement the trait for a reference to your type

Instead of implementing the trait for your type, implement it for a reference to your type. The trait never needs to know anything about lifetimes this way.

那么trait函数必须按值接受其参数.在您的情况下,您将实现该特征以供参考:

The trait function then must take its argument by value. In your case you will implement the trait for a reference:

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()
    }
}

您的fooget函数现在变得简单

fn fooget<T: Foo>(foo: T) {}

此问题是fooget函数实际上不知道T&Bar.当您调用get函数时,实际上是在移出foo变量.您不会移出对象,而只是移动参考.如果您的fooget函数尝试调用get两次,该函数将无法编译.

The problem with this is that the fooget function doesn't know T is in reality a &Bar. When you call the get function, you are actually moving out of the foo variable. You don't move out of the object, you just move the reference. If your fooget function tries to call get twice, the function won't compile.

如果您想让fooget函数仅接受为引用实现了Foo特征的参数,则需要明确声明此绑定:

If you want your fooget function to only accept arguments where the Foo trait is implemented for references, you need to explicitly state this bound:

fn fooget_twice<'a, T>(foo: &'a T)
where
    &'a T: Foo,
{}

where子句可确保仅对为引用实现了Foo而不是类型的引用调用此函数.两者都可以实现.

The where clause makes sure that you only call this function for references where Foo was implemented for the reference instead of the type. It may also be implemented for both.

从技术上讲,编译器可以自动推断fooget_twice的生存期,因此您可以将其编写为

Technically, the compiler could automatically infer the lifetime in fooget_twice so you could write it as

n fooget_twice<T>(foo: &T)
where
    &T: Foo,
{}

但它还不够聪明.

对于更复杂的情况,可以使用尚未实现的Rust功能: issue 44265 中进行跟踪.

For more complicated cases, you can use a Rust feature which is not yet implemented: Generic Associated Types (GATs). Work for that is being tracked in issue 44265.

这篇关于如何在关联类型中指定生命周期参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆