【问题标题】:How can generic closures be stored in generic structures?泛型闭包如何存储在泛型结构中?
【发布时间】:2015-06-08 06:52:00
【问题描述】:

我有一个通用结构,我想在其中存储一个闭包。这个闭包的参数和返回类型与结构的最终类型直接相关。如何定义这样的结构?

我知道的唯一方法是使用 where 关键字组合类型。但是,当尝试编译代码时,编译器会停止并抱怨没有使用 T't

我可以通过添加使用 T't 的无用变量来编译它,但我想有更好、更正确的原因。

以下代码 (playpen) 编译。删除无用的变量,它不会:

pub struct GenericContainer<'t, T: 't, F> where F: Fn(&'t [T]) -> Option<&'t [T]> {
    generic_closure: F,
    unused: Option<&'t T>
}

impl<'t, T: 't, F> GenericContainer<'t, T, F> where 
    F: Fn(&'t [T]) -> Option<&'t [T]> {

    pub fn new(gc: F) -> Self {
        GenericContainer {
            generic_closure: gc,
            unused: None
        }
    }

    pub fn execute(&self, slice: &'t [T]) -> Option<&'t [T]> {
        let g = &self.generic_closure;
        let _ = &self.unused;
        g(slice)
    }
}

fn main() {
    let g = GenericContainer::new(|s| if s.len() == 0 {None} else {Some(&s[..1])});
    assert!(g.execute(b"   ") == Some(b" "));
    println!("ok");
}

【问题讨论】:

  • 对那些可能也误入歧途的人的友好提示:确保您真的想以这种方式使用闭包。通常,走正常的 struct+traits 路线会完成你想做的事情,并且不会产生唯一类型的结构。

标签: generics closures rust


【解决方案1】:

您处于典型的“高等级”情况:'tT 仅用于定义类型 F

首先,对于生命周期,您可以使用 rust 的高级生命周期语法:

where F: for<'t> Fn(&'t [T]) -> Option<&'t [T]>

然后从你的结构类型中删除它。

T 做类似的事情会很好,但是Rust 目前不支持更高级别的类型。所以你最好的方法可能是遵循编译器的建议,并使用std::maker::PhantomData

你最终会得到这样的类型:

pub struct GenericContainer<T, F>
    where F: for<'t> Fn(&'t [T]) -> Option<&'t [T]>
{
    generic_closure: F,
    _marker: ::std::marker::PhantomData<T>
}

请注意,在 _marker 前加上 _ 可防止将其检测为未使用。

然后,您只需要更新您的实现:

impl<T, F> GenericContainer<T, F> where 
    F: for<'t> Fn(&'t [T]) -> Option<&'t [T]> {

    pub fn new(gc: F) -> Self {
        GenericContainer {
            generic_closure: gc,
            _marker: ::std::marker::PhantomData
        }
    }

    pub fn execute<'t>(&self, slice: &'t [T]) -> Option<&'t [T]> {
        let g = &self.generic_closure;
        g(slice)
    }
}

【讨论】:

    猜你喜欢
    • 2015-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多