我对如何让它工作有点难过,我已经把它从真实的东西中删掉了。我写了一个特征:
pub trait Renderable<F: Fn(&PropertyTags)> {
fn set_property_changed_callback(&mut self, callback: Option<F>);
}
add_child
的 'child' 参数受限制,PropertyTags
只是一个枚举。我包含了 child
类型的模拟实现来演示我的用法:
pub struct Child<F: Fn(&PropertyTags)> {
property_changed_callback: Option<F>,
}
impl<F: Fn(&PropertyTags)> Renderable<F> for Child<F> {
fn set_property_changed_callback(&mut self, callback: Option<F>) {
self.property_changed_callback = callback;
}
}
然后这些将用作:
pub fn add_child<REND, C>(&mut self, child: &mut REND)
where C: Fn(&PropertyTags),
REND: Renderable<C>
{
let tc = Some(|property_tag: &PropertyTags|{
});
child.set_property_changed_callback(tc);
}
我收到错误:
child.set_property_changed_callback(tc);
| ^^ expected type parameter, found closure
|
= note: expected type `std::option::Option<C>`
= note: found type `std::option::Option<[closure@src/rendering/mod.rs:74:31: 76:18]>`
= help: here are some functions which might fulfill your needs:
- .take()
- .unwrap()
我设置了一个最小的 Playground 示例,它重现了这里的问题:https://play.rust-lang.org/?gist=bcc8d67f25ac620fe062032d8737954b&version=stable&backtrace=0
最佳答案
问题是 add_child
声称接受任何Renderable<C>
, 其中C
可以是实现 Fn(&PropertyTags)
的任何类型, 但随后该函数尝试为其提供可能与 C
不同的特定闭包类型.
为了让它工作,add_child
的签名应该是这样的:
pub fn add_child<REND>(&mut self, child: &mut REND)
where REND: Renderable<AddChildCallback>
哪里AddChildCallback
是具体类型的名称(实现了 Fn(&PropertyTags)
)。
这里的困难在于,一方面,闭包类型没有可以在 Rust 代码中使用的名称,另一方面,实现 Fn
手动是不稳定的,所以它需要一个夜间编译器。
我还会注意到,通过将回调类型设为类型参数,Renderable
在设置第一个回调后不能分配不同类型的回调,因为第一个回调将确定 Renderable
的具体类型.这可能适合您的使用,我只是想确保您了解这一点。
如果您想要一个适用于稳定编译器(从 Rust 1.14.0 开始)的解决方案,那么您将不得不封装回调。 add_child
的签名将如下所示:
pub fn add_child<REND>(&mut self, child: &mut REND)
where REND: Renderable<Box<Fn(&PropertyTags)>>
Here是更新的 Playground 链接,其中包含 Fn
的示例实现.请注意 call
的参数, call_mut
和 call_once
按照特征定义的要求,作为元组传递。为了完整起见,代码转载如下:
struct RenderableCallback {
}
impl<'a> Fn<(&'a PropertyTags,)> for RenderableCallback {
extern "rust-call" fn call(&self, args: (&'a PropertyTags,)) -> Self::Output {
}
}
impl<'a> FnMut<(&'a PropertyTags,)> for RenderableCallback {
extern "rust-call" fn call_mut(&mut self, args: (&'a PropertyTags,)) -> Self::Output {
}
}
impl<'a> FnOnce<(&'a PropertyTags,)> for RenderableCallback {
type Output = ();
extern "rust-call" fn call_once(self, args: (&'a PropertyTags,)) -> Self::Output {
}
}
关于rust - 将闭包传递给特征方法 : expected type parameter, 找到闭包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41664325/