我试图用可以实现的方法来定义特征,以返回引用或拥有的值。可以实现的特征方法返回引用或拥有的值
喜欢的东西:
struct Type;
trait Trait {
type Value;
fn f(&self) -> Self::Value;
}
impl Trait for() {
type Value = Type;
fn f(&self) -> Self::Value {
Type
}
}
impl Trait for (Type,) {
type Value = &Type; // error[E0106]: missing lifetime specifier
fn f(&self) -> Self::Value {
&self.0
}
}
这段代码不工作,虽然,因为&Type
缺少一生符。我希望&Type
的寿命与&self
(即fn f<'a>(&'a self) -> &'a Type
)的寿命相同,但我不知道如何在Rust中表达这一点。
我设法找到一对夫妇的方式,使此代码的工作,但我不爱他们之一:
添加一个明确的一生来性状本身:
trait Trait<'a> { type Value; fn f<'b>(&'b self) -> Self::Value where 'b: 'a; } impl<'a> Trait<'a> for() { type Value = Type; fn f<'b>(&'b self) -> Self::Value where 'b: 'a { Type } } impl<'a> Trait<'a> for (Type,) { type Value = &'a Type; fn f<'b>(&'b self) -> Self::Value where 'b: 'a { &self.0 } }
我不喜欢这个解决方案,任何使用
Trait
的东西都需要一个明确的生命周期(我认为这并不是本质上必需的),再加上这个特性看起来不太复杂。返回的东西,可能会或可能不会是一个参考 - 像
std::borrow::Cow
:trait Trait { type Value; fn f<'a>(&'a self) -> Cow<'a, Self::Value>; } impl Trait for() { type Value = Type; fn f<'a>(&'a self) -> Cow<'a, Self::Value> { Cow::Owned(Type) } } impl Trait for (Type,) { type Value = Type; fn f<'a>(&'a self) -> Cow<'a, Self::Value> { Cow::Borrowed(&self.0) } }
我不喜欢这样的解决方案是,
().f()
是Cow<_>
:我需要调用().f().into_owned()
到获得我的Type
。这似乎是不必要的(并且在使用Trait
作为特征对象时可能会导致一些可忽略的运行时开销)。另外请注意,
Cow
是不好的,因为它需要Self::Value
实现ToOwned
(因此,实际上,Clone
),这是太强烈的要求。无论如何,轻松实施Cow
的替代方案都没有这样的限制。
有没有其他解决方案来解决这个问题?什么是标准/最常见/首选的?
“为特质本身添加明确的生命期”正是我如何做的(尽管可能只有一个生命周期)。也许你可以进一步解释为什么你“相信不是本质上必要的”,因为对我来说它看起来非常必要 - 你*需要*将一生与“自我”类型联系起来,以防止在值出去之后使用引用的范围。 – Shepmaster
@Shepmaster:哦,你的意思是'特质特质<'a> {type Value; fn f(&'a self) - > Self :: Value; ''?我确信我尝试了它,但没有奏效,但显然我错了。你是对的,阅读你的评论,并定义没有“b”的特质使我意识到“a”必须是特性的内在... – peoro
是的,我会用'impl Trait <'static> for ){...}',但除此之外...... – Shepmaster