rust - 将闭包传递给特征方法 : expected type parameter, 找到闭包

标签 rust closures

我对如何让它工作有点难过,我已经把它从真实的东西中删掉了。我写了一个特征:

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_mutcall_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/

相关文章:

perl - 不本地化循环变量会给出不同的结果

ios - 在使用 SFRestAPI 时一起使用部分和 tableviewcells 时出错

ios - 如何从 Swift 中的闭包返回值?

rust - 为什么我不能在将 &mut 引用传递给接受泛型类型的函数后重用它?

rust - 为什么 Rust 借用检查器拒绝这个函数?

url - Rust 标准库中是否具有从 URL 下载文件的功能

javascript - JavaScript闭包如何工作?

generics - 当 T 没有实现 Clone 时,为什么不能为泛型 Option<T> 克隆 None?

rust - 为什么 `cargo build`紧接着 `cargo check`重新编译了一些依赖?

python - Python 中的闭包和循环