自动导出 Arc 的特征实现
Automatically derive traits implementation for Arc
我有一个特征和一个 struct
实现它。 Arc
包裹的struct
可以调用trait的方法,但是Arc
本身并没有实现:
use std::sync::Arc;
trait Foo{
fn bar(&self);
}
struct A;
impl Foo for A{
fn bar(&self){ }
}
fn test<A: Foo>(arc_a: Arc<A>){
let foo_obj: & dyn Foo = &arc_a; //the trait bound `std::sync::Arc<A>: Foo` is not satisfied
}
以下代码工作正常:
use std::sync::Arc;
trait Foo{
fn bar(&self);
}
struct A;
impl Foo for A{
fn bar(&self){ }
}
impl<A> Foo for Arc<A> //Manually implemented
where
A: Foo
{
fn bar(&self){ self.bar() }
}
fn test<A: Foo>(arc_a: Arc<A>){
let foo_obj: & dyn Foo = &arc_a;
}
有没有办法自动派生这种特征的实现?
您必须手动实施它们。虽然您手动实施 Foo for Arc<A>
看起来完全微不足道,但重要的部分是“隐藏”在 self.bar()
中,其中从 self: &Arc<A>
到 &A
发生自动取消引用。请记住,您的实现 Foo for Arc<A>
实际上可能完全不同;不过,在现实世界中,我们通常只需要“deref impl”。
在你的第一个例子中
fn test<A: Foo>(arc_a: Arc<A>){
let foo_obj: &dyn Foo = &arc_a;
}
如果您执行 = &*arc_a
,这将编译,因为 *arc_a
从 Arc<A>
取消引用到 A
,然后 &*arc_a
是一个 &dyn Foo
.
在您的第二个示例中,您提供了手动实施 for Arc<A>
impl<A> Foo for Arc<A> where A: Foo {
fn bar(&self){ self.bar() }
}
在这里,deref - 上面是显式的 - 现在隐含在 self.bar()
中。这使您免于手动取消引用,但 impl 可能完全不同。例如:
impl Foo for A{
fn bar(&self){ println!("This is fine") }
}
impl<A> Foo for Arc<A>
where
A: Foo
{
fn bar(&self) { panic!() }
}
fn test<A: Foo>(arc_a: Arc<A>){
let foo_obj: & dyn Foo = &arc_a;
foo_obj.bar()
}
fn main() {
test(Arc::new(A))
}
上面的程序会崩溃,因为 foo_obj
使用了 impl for Arc<A>
。如果将 test
中的行更改为 = &*arc_a
,则使用 impl for A
,程序将打印“This is fine”。
如果您只需要 Foo
的普通智能指针的微不足道的实现,您可以通过宏来实现:
macro_rules! deref_impl {
($($sig:tt)+) => {
impl $($sig)+ {
fn bar(&self) {
(**self).bar()
}
}
};
}
deref_impl!(<'a, N> Foo for &'a N where N: Foo + ?Sized);
deref_impl!(<'a, N> Foo for &'a mut N where N: Foo + ?Sized);
deref_impl!(<N> Foo for Box<N> where N: Foo + ?Sized);
deref_impl!(<N> Foo for std::rc::Rc<N> where N: Foo + ?Sized);
deref_impl!(<N> Foo for std::sync::Arc<N> where N: Foo + ?Sized);
我有一个特征和一个 struct
实现它。 Arc
包裹的struct
可以调用trait的方法,但是Arc
本身并没有实现:
use std::sync::Arc;
trait Foo{
fn bar(&self);
}
struct A;
impl Foo for A{
fn bar(&self){ }
}
fn test<A: Foo>(arc_a: Arc<A>){
let foo_obj: & dyn Foo = &arc_a; //the trait bound `std::sync::Arc<A>: Foo` is not satisfied
}
以下代码工作正常:
use std::sync::Arc;
trait Foo{
fn bar(&self);
}
struct A;
impl Foo for A{
fn bar(&self){ }
}
impl<A> Foo for Arc<A> //Manually implemented
where
A: Foo
{
fn bar(&self){ self.bar() }
}
fn test<A: Foo>(arc_a: Arc<A>){
let foo_obj: & dyn Foo = &arc_a;
}
有没有办法自动派生这种特征的实现?
您必须手动实施它们。虽然您手动实施 Foo for Arc<A>
看起来完全微不足道,但重要的部分是“隐藏”在 self.bar()
中,其中从 self: &Arc<A>
到 &A
发生自动取消引用。请记住,您的实现 Foo for Arc<A>
实际上可能完全不同;不过,在现实世界中,我们通常只需要“deref impl”。
在你的第一个例子中
fn test<A: Foo>(arc_a: Arc<A>){
let foo_obj: &dyn Foo = &arc_a;
}
如果您执行 = &*arc_a
,这将编译,因为 *arc_a
从 Arc<A>
取消引用到 A
,然后 &*arc_a
是一个 &dyn Foo
.
在您的第二个示例中,您提供了手动实施 for Arc<A>
impl<A> Foo for Arc<A> where A: Foo {
fn bar(&self){ self.bar() }
}
在这里,deref - 上面是显式的 - 现在隐含在 self.bar()
中。这使您免于手动取消引用,但 impl 可能完全不同。例如:
impl Foo for A{
fn bar(&self){ println!("This is fine") }
}
impl<A> Foo for Arc<A>
where
A: Foo
{
fn bar(&self) { panic!() }
}
fn test<A: Foo>(arc_a: Arc<A>){
let foo_obj: & dyn Foo = &arc_a;
foo_obj.bar()
}
fn main() {
test(Arc::new(A))
}
上面的程序会崩溃,因为 foo_obj
使用了 impl for Arc<A>
。如果将 test
中的行更改为 = &*arc_a
,则使用 impl for A
,程序将打印“This is fine”。
如果您只需要 Foo
的普通智能指针的微不足道的实现,您可以通过宏来实现:
macro_rules! deref_impl {
($($sig:tt)+) => {
impl $($sig)+ {
fn bar(&self) {
(**self).bar()
}
}
};
}
deref_impl!(<'a, N> Foo for &'a N where N: Foo + ?Sized);
deref_impl!(<'a, N> Foo for &'a mut N where N: Foo + ?Sized);
deref_impl!(<N> Foo for Box<N> where N: Foo + ?Sized);
deref_impl!(<N> Foo for std::rc::Rc<N> where N: Foo + ?Sized);
deref_impl!(<N> Foo for std::sync::Arc<N> where N: Foo + ?Sized);