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

我对如何使它正常工作有些困惑,我已经从真实的东西中删除了它。我写了一个特质:

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

 

最佳答案

问题在于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的示例实现。请注意,根据trait定义的要求,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 {
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

web3.0前沿技术研究者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值