我想使特征类似于以下结构(我的特定用例有点复杂,但这捕获了我遇到的问题和错误)。我的问题是最后一次实现的生命周期。我想我需要将它们压缩到特征定义中,但是我不确定如何。我如何整理生命周期,以便进行汇总?
Rust playground link to code
trait MyTrait<TIn> {
fn f<TOut, F>(f: F, x: Self) -> TOut
where
F: Fn(TIn) -> TOut;
}
impl<T> MyTrait<T> for T {
fn f<TOut, F>(f: F, x: T) -> TOut
where
F: Fn(T) -> TOut,
{
f(x)
}
}
impl<T> MyTrait<T> for &T
where
T: Clone,
{
fn f<TOut, F>(f: F, x: &T) -> TOut
where
F: Fn(T) -> TOut,
{
f(x.clone())
}
}
// This impl fails to compile:
impl<T> MyTrait<&T> for T {
fn f<TOut, F>(f: F, x: T) -> TOut
where
F: Fn(&T) -> TOut,
{
f(&x)
}
}
最佳答案
类型签名
impl<T> MyTrait<&T> for T {
fn f<TOut, F>(f: F, x: T) -> TOut
where
F: Fn(&T) -> TOut,
{
}
}
对
impl<'a, T: 'a> MyTrait<&'a T> for T {
fn f<TOut, F>(f: F, x: T) -> TOut
where
F: for<'r> Fn(&'r T) -> TOut,
{
}
}
这比特征的类型签名更笼统。使用
impl<'a, T: 'a> MyTrait<&'a T> for T {
fn f<TOut, F>(f: F, x: T) -> TOut
where
F: Fn(&'a T) -> TOut,
{
}
}
将允许它编译,但将实现限制为非终止代码或不安全代码。
impl<'a, T: 'a> MyTrait<&'a T> for T {
fn f<TOut, F>(f: F, x: T) -> TOut
where
F: Fn(&'a T) -> TOut,
{
//panic!(); or
f(unsafe { &*(&x as *const T) })
}
}
不安全的版本在释放后很容易引起使用,例如
println!("{:?}", String::f(|x: &String| x, "aa".to_string()));
您可以改为将
F
(Playground)的边界向上移动trait MyTrait<TIn, F, TOut>
where
F: Fn(TIn) -> TOut,
{
fn f(f: F, x: Self) -> TOut;
}
impl<T, F, TOut> MyTrait<T, F, TOut> for T
where
F: Fn(T) -> TOut,
{
fn f(f: F, x: T) -> TOut {
f(x)
}
}
impl<T, F, TOut> MyTrait<T, F, TOut> for &T
where
T: Clone,
F: Fn(T) -> TOut,
{
fn f(f: F, x: &T) -> TOut {
f(x.clone())
}
}
impl<T, F, TOut> MyTrait<&T, F, TOut> for T
where
F: Fn(&T) -> TOut,
{
fn f(f: F, x: T) -> TOut {
f(&x)
}
}
关于rust - 通用特征实现中的生命周期,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56759389/