我想定义一个特质(trait),其中有一个方法可以实现返回引用或拥有的值。
例如:
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中表达这个意思。我找到了一些让这段代码工作的方法,但我并不喜欢它们:
Adding an explicit lifetime to the trait itself:
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 } }
What I don't like of this solution is that anything using
Trait
needs an explicit lifetime (which I believe is not intrinsically necessary), plus the trait seems unnecessarily complicated to implement.Returning something that might or might not be a reference - like
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) } }
What I don't like of this solution is that
().f()
is aCow<_>
: I'd need to call().f().into_owned()
to obtain myType
. That seems unnecessary (and might result in some negligible run-time overhead when usingTrait
as a trait object).Also note that
Cow
is not good since it requires thatSelf::Value
implementsToOwned
(thus, practically,Clone
), which is too strong of a requirement. It's anyways easy to implement an alternative toCow
without such constraints.
这个问题是否有其他解决方案?标准/最常见/首选方案是什么?
impl Trait<'static> for () { ... }
,但除此之外... - ShepmasterSelf
内部的引用,还是指向Self
引用的不相关对象? - Matthieu M.self
内对象的引用(即&self.0
),但我认为如果我想要impl<'a> Trait for (&'a Type,)
,那么引用可能会是self.0
。 - peoro