通用闭包如何存储在通用结构中?
How can generic closures be stored in generic structures?
我有一个要在其中存储闭包的通用结构。此闭包的参数和 return 类型与结构的最终类型直接相关。如何定义这样的结构?
我知道的唯一方法是使用 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");
}
您处于典型的"higher-ranked-stuff"情况:'t
和T
仅用于定义类型F
。
首先,对于生命周期,可以使用rust的higher-ranked-lifetimes语法:
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)
}
}
我有一个要在其中存储闭包的通用结构。此闭包的参数和 return 类型与结构的最终类型直接相关。如何定义这样的结构?
我知道的唯一方法是使用 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");
}
您处于典型的"higher-ranked-stuff"情况:'t
和T
仅用于定义类型F
。
首先,对于生命周期,可以使用rust的higher-ranked-lifetimes语法:
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)
}
}