gpt4 book ai didi

rust - 如何为具有 "rented"引用的类型实现特征

转载 作者:行者123 更新时间:2023-11-29 08:07:23 25 4
gpt4 key购买 nike

注意:我试图让这篇文章尽可能简洁,完整的代码可以在 https://github.com/pchampin/pair_trait 找到。 .

问题

我定义了以下特征:

pub trait Pair {
type Item: Borrow<str>;
fn first(&self) -> &Self::Item;
fn second(&self) -> &Self::Item;
}

我对 (T,T) 有这个特性的通用实现和 [T;2]对于任何 T 实现 Borrow<str> .

我也有一个类型,用 rental 构建 crate ,包含一个 String和两个 Cow<str>从那个字符串借来的:

#[rental(covariant)]
pub struct SelfSustainedPair {
line: String,
pair: (Cow<'line, str>, Cow<'line, str>),
}

我想要这种类型来实现 Pair上面的特征,但我找不到办法。

尝试 #0

impl SelfSustainedPair {
pub fn first(&self) -> &Cow<str> { self.suffix().first() }
pub fn second(&self) -> &Cow<str> { self.suffix().second() }
}

我知道这不是特性的实现,但我只是想确保我可以实现这些方法 firstsecond .答案是肯定的:上面的代码可以编译。

尝试 #1

impl Pair for SelfSustainedPair {
type Item = Cow<str>;
fn first(&self) -> &Cow<str> { self.suffix().first() }
fn second(&self) -> &Cow<str> { self.suffix().second() }
}

编译失败,第二行显示“expected lifetime parameter”消息。

这令人沮丧,因为它非常接近上面的 #0 尝试。

尝试#2

impl<'a> Pair for SelfSustainedPair {
type Item = Cow<'a, str>;
fn first(&self) -> &Cow<'a, str> { self.suffix().first() }
fn second(&self) -> &Cow<'a, str> { self.suffix().second() }
}

编译器在这里提示第一行 ( impl<'a> ) 的“无约束生命周期参数”。

尝试 #3

我修改了我的特征 Pair这样它就需要一个生命周期参数。令人惊讶的是,即使在特征的定义中从未使用 liferime 参数,这仍然有效...

然后我写道:

impl<'a> Pair<'a> for SelfSustainedPair {
type Item = Cow<'a, str>;
fn first(&self) -> &Cow<'a, str> { self.suffix().first() }
fn second(&self) -> &Cow<'a, str> { self.suffix().second() }
}

现在编译器提示它在这两种方法中“无法推断出 autoref 的适当生命周期”...

无论如何,我的直觉是这不是正确的路径:返回的生命周期 Cow不能独立于 self 指定...

尝试#4

理想情况下,这就是我想写的:

impl Pair for SelfSustainedPair {
type Item = Cow<'self, str>;
fn first(&self) -> &Cow<str> { self.suffix().first() }
fn second(&self) -> &Cow<str> { self.suffix().second() }
}

但显然,编译器不知道 self生命周期。

最佳答案

不幸的是,目前无法实现完全预期的设计。不过,我们可以将尝试 #3 调整为某种工作。

返回 &Self::Item 的想法格式有点不正确,因为关联类型 Item已经代表借来的值(value)。直接返回更有意义:

pub trait Pair {
type Item: Borrow<str>;
fn first(&self) -> Self::Item;
fn second(&self) -> Self::Item;
}

但是你会因无法描述这个 Item 而跌跌撞撞作为Cow<'a, str>其中 'aself 的生命周期.尝试 3 通过向特征本身添加一个生命周期参数来接近解决方案,从而使这个任意生命周期成为特征的更高级别的参数。

pub trait Pair<'a> {
type Item: 'a + Borrow<str>;
fn first(&'a self) -> Self::Item;
fn second(&'a self) -> Self::Item;
}

Pair<'a>现在定义一对绑定(bind)到 'a 的元素, 并且不一定包含在 self 中.一种可能的实现方式:

impl<'a> Pair<'a> for (String, String) {
type Item = Cow<'a, str>;

fn first(&'a self) -> Self::Item {
Cow::Borrowed(&self.0)
}
fn second(&'a self) -> Self::Item {
Cow::Borrowed(&self.1)
}
}

Full example in the Rust Playground

这种方法的代价是污染所有依赖于具有更高排名特征边界的特征的 API,因此我们可以实现 Pair<'a>一生一世'a .例如:

fn foo<T>(pair: T)
where
for<'a> T: Pair<'a>,
{
unimplemented!()
}

为了实现这个'self约束关联类型的生命周期 Item , 我们需要 Generic Associated Types (服务贸易协定)。一旦实现,我们将能够编写如下内容:

pub trait Pair {
type Item<'a>: Borrow<str>;
fn first(&'a self) -> Self::Item<'a>;
fn second(&'a self) -> Self::Item<'a>;
}

impl Pair for (String, String) {
type Item<'a> = Cow<'a, str>;

fn first(&'a self) -> Self::Item<'a> {
Cow::Borrowed(&self.0)
}
fn second(&'a self) -> Self::Item<'a> {
Cow::Borrowed(&self.1)
}
}

关于rust - 如何为具有 "rented"引用的类型实现特征,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52152052/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com