假设我有以下代码:
trait Saluter {
fn hello(&self);
fn bye(&self);
}
struct A {}
struct B {}
impl Saluter for A {
fn hello(&self) {
println!("Hello A!");
}
fn bye(&self) {
println!("Bye A!");
}
}
impl Saluter for B {
fn hello(&self) {
println!("Hello B!");
}
fn bye(&self) {
println!("Bye B!");
}
}
pub struct Foo {
saluter: Box<dyn Saluter>,
salute: fn (&dyn Saluter),
}
fn main() {
let x = Foo {saluter: Box::new(A{}), salute: Saluter::hello};
let y = Foo {saluter: Box::new(B{}), salute: Saluter::bye};
(x.salute)(x.saluter.borrow()); //Should print "Hello A!"
(y.salute)(y.saluter.borrow()); //Should print "Hello B!"
}
基本上我试图独立操作调用者和被调用的方法。但是我得到以下编译错误:
let x = Foo {saluter: Box::new(A{}), salute: Saluter::hello};
| ^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected fn pointer `for<'r> fn(&'r (dyn Saluter + 'r))`
found fn pointer `for<'r> fn(&'r dyn Saluter)`
同样的错误显然适用于 y。我最近才开始学习 Rust,所以我对 Rust 的生命周期参数一点也不流利,但在我看来它在抱怨这个,尽管我找不到 (dyn Salute + 'r) 的确切含义。
有没有办法实现我想要的,或者这在 Rust 中根本不可能?在 C++ 中,我可以轻松地使用指向基类的指针来完成,但我正在努力寻找如何在 Rust 中实现这一点。
感谢您的帮助!
我能够通过限制函数指针类型来编译你的代码:
pub struct Foo {
saluter: Box<dyn Saluter>,
salute: fn (&(dyn Saluter + 'static)),
}
这个额外的
+ 'static
约束意味着存储在 salute
中的 Foo
函数指针只能与实现 Saluter
的 types 一起使用,它没有有限的生命周期——笼统地说,“不包含非静态引用”。也就是说,如果你有
struct B<'x> { ... }
impl<'x> Saluter for B<'x> {}
则该功能将无法使用。然而,这是一个罕见的案例。
不幸的是,我不确定为什么函数指针
Saluter::hello
不能是您的原始代码所隐含的完全通用类型,
salute: for<'a> fn (&'a (dyn Saluter + 'a)),
所以我无法给出完整的解释
您在
Saluter
结构中使用由 Foo
绑定的泛型类型:
pub struct Foo<T> where T: Saluter {
saluter: Box<T>,
salute: fn (&T),
}