以 &Box<T> 和 &T 作为参数的因式分解方法
Factorize methods taking &Box<T> and &T as argument
我有一个方法需要用特征参数调用(我们称之为 Listener
)。原因是有时我之前将此特征参数存储到父结构中,因此它在 Box
中,有时不在
中
所以我有两种方法:
fref<T>(t: &T) where T: Listener
fbox(t: &Box<dyn Listener>)
我希望他们都打电话给 f(t: ??)
。现在我复制了 fref
和 fbox
中的代码,但效果不佳。所以我正在寻找 f
的签名,它可以从 fref
和 fbox
调用它来分解我的代码。我希望 Box
实现的特征之一等同于 &
(或者至少在某处找到共同点)。
我尝试了以下方法:
- 正在写入
f<T>(t: &T) where T: Listener
但我无法从 fbox
调用(Listener
未由 Box<dyn Listener>
实现)。
然后将调用从 fbox
更改为 f(&*t)
以拆箱我的 Box<Listener>
但是因为 t
不是 Size
d我不能。
写 f<T>(t: &T) where T: std::borrow::Borrow<Listener>
但我无法从 fref
调用(Borrow
未由 Listener
实现)
- 同
AsRef<Listener>
- 上次尝试
Deref
playground:
trait Listener {}
struct Mouse {}
impl Listener for Mouse {}
fn fbox(t: &Box<Listener>) {
f(t);
}
fn fref<T>(t: &T)
where
T: Listener,
{
f(t);
}
fn f<T>(_t: &T)
where
T: std::ops::Deref<Target = Listener>,
{
}
fn create_listener() -> impl Listener {
Mouse {}
}
fn main() {
let mouse = create_listener();
let box_mouse: Box<Listener> = Box::new(Mouse {});
fref(&mouse);
fbox(&box_mouse);
}
Listener
是一个特征,所以 Box<Listener>
是 真正的 一个特征对象,Box<dyn Listener>
- 不幸的是 dyn
关键字目前是可选的。 Box<dyn Listener>
和 &Mouse
都实现了 Deref
,关联的 Target
类型实现了 Listener
。在 &Mouse
的情况下,deref Target
是 Mouse
,但在 Box<dyn Listener>
的情况下,它是一个未知对象,dyn Listener
of 未知 尺寸。
要捕获所有这些信息,您可以这样写 f
:
fn f<T, L>(_listener: &T)
where
T: Deref<Target = L>,
L: Listener + ?Sized
{
}
然后像这样从每个函数调用它:
fn fbox(listener: &Box<dyn Listener>) {
f(listener);
}
fn fref<L>(listener: &L)
where
L: Listener
{
f(&listener);
}
另一种可能更简单的查看方式是放弃 Deref
约束并仅使用普通引用。使用 Box::as_ref
将 Box
转换为引用以便调用它。 ?Sized
un-constraint 对于 trait object case 仍然是必需的,并且仍然有效,因为值总是在指针后面:
fn fbox(listener: &Box<dyn Listener>) {
f(listener.as_ref());
}
fn fref<L>(listener: &L) where L: Listener {
f(listener);
}
fn f<L>(_listener: &L)
where
L: Listener + ?Sized
{
}
我有一个方法需要用特征参数调用(我们称之为 Listener
)。原因是有时我之前将此特征参数存储到父结构中,因此它在 Box
中,有时不在
所以我有两种方法:
fref<T>(t: &T) where T: Listener
fbox(t: &Box<dyn Listener>)
我希望他们都打电话给 f(t: ??)
。现在我复制了 fref
和 fbox
中的代码,但效果不佳。所以我正在寻找 f
的签名,它可以从 fref
和 fbox
调用它来分解我的代码。我希望 Box
实现的特征之一等同于 &
(或者至少在某处找到共同点)。
我尝试了以下方法:
- 正在写入
f<T>(t: &T) where T: Listener
但我无法从fbox
调用(Listener
未由Box<dyn Listener>
实现)。 然后将调用从
fbox
更改为f(&*t)
以拆箱我的Box<Listener>
但是因为t
不是Size
d我不能。写
f<T>(t: &T) where T: std::borrow::Borrow<Listener>
但我无法从fref
调用(Borrow
未由Listener
实现)- 同
AsRef<Listener>
- 上次尝试
Deref
playground:
trait Listener {}
struct Mouse {}
impl Listener for Mouse {}
fn fbox(t: &Box<Listener>) {
f(t);
}
fn fref<T>(t: &T)
where
T: Listener,
{
f(t);
}
fn f<T>(_t: &T)
where
T: std::ops::Deref<Target = Listener>,
{
}
fn create_listener() -> impl Listener {
Mouse {}
}
fn main() {
let mouse = create_listener();
let box_mouse: Box<Listener> = Box::new(Mouse {});
fref(&mouse);
fbox(&box_mouse);
}
Listener
是一个特征,所以 Box<Listener>
是 真正的 一个特征对象,Box<dyn Listener>
- 不幸的是 dyn
关键字目前是可选的。 Box<dyn Listener>
和 &Mouse
都实现了 Deref
,关联的 Target
类型实现了 Listener
。在 &Mouse
的情况下,deref Target
是 Mouse
,但在 Box<dyn Listener>
的情况下,它是一个未知对象,dyn Listener
of 未知 尺寸。
要捕获所有这些信息,您可以这样写 f
:
fn f<T, L>(_listener: &T)
where
T: Deref<Target = L>,
L: Listener + ?Sized
{
}
然后像这样从每个函数调用它:
fn fbox(listener: &Box<dyn Listener>) {
f(listener);
}
fn fref<L>(listener: &L)
where
L: Listener
{
f(&listener);
}
另一种可能更简单的查看方式是放弃 Deref
约束并仅使用普通引用。使用 Box::as_ref
将 Box
转换为引用以便调用它。 ?Sized
un-constraint 对于 trait object case 仍然是必需的,并且仍然有效,因为值总是在指针后面:
fn fbox(listener: &Box<dyn Listener>) {
f(listener.as_ref());
}
fn fref<L>(listener: &L) where L: Listener {
f(listener);
}
fn f<L>(_listener: &L)
where
L: Listener + ?Sized
{
}