首页 文章

将闭包传递给trait方法:期望的类型参数,找到闭包

提问于
浏览
3

我对如何使这个工作有点困惑,我已经从真实的东西中删除了它 . 我写了一个特点:

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()

我已经设置了一个最小的游乐场示例,可以在这里重现问题:https://play.rust-lang.org/?gist=bcc8d67f25ac620fe062032d8737954b&version=stable&backtrace=0

1 回答

  • 4

    问题是 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是一个更新的游乐场链接,其示例实现为 Fn . 请注意, callcall_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 {
        }
    }
    

相关问题