在下面的代码中,据我理解,SimpleSpawner
应该有一个已知的大小,因为它相当于一个函数指针+一个单个u8
值,但是这段代码给出了错误the size for values of type
(dyn SimpleSpawner<for 'a> Output = u8> + 'static)cannot be known at compilation time
。理想情况下,我可以使用函数指针,但函数指针和闭包在Rust中不兼容。
(Rust Playground Link)
#[derive(Clone)]
pub struct RandomTable<T> {
pub entries: Vec<T>,
}
impl<T> RandomTable<T> {
pub fn new() -> Self {
RandomTable {
entries: Vec::new(),
}
}
}
// pub type SimpleSpawner = fn(u8) -> u8;
// pub type SimpleSpawner = dyn Fn(&mut u8) -> u8;
pub trait SimpleSpawner: Fn(&mut u8) -> u8 + Sized {}
// changed from `-> RandomTable<SimpleSpawner>`
pub fn room_table(map_depth: i32) -> RandomTable<dyn SimpleSpawner> {
RandomTable::new()
}
1条答案
按热度按时间fd3cxomn1#
这里有不少误解。
SimpleSpawner应该有一个已知的大小,因为它相当于一个函数指针+一个u8值
SimpleSpawner
是trait。这意味着它的大小是未知的,它可能是一个实现它的千兆字节大的结构。trait仅仅意味着一个给定的类型具有特定的功能,它对它的大小没有任何说明。Sized
trait仍然没有说明实际大小。它只是说,在编译时,编译器现在知道它的大小。有许多类型没有大小,这意味着编译器不能争论它们的大小,因此它们必须通过引用(&
对unsized traits的引用具有已知的大小)或通过Box
(这意味着我们将它们移到堆上,因此在堆栈上我们不再关心它们的大小)进行交互。函数指针+单个u8值
我不知道你从哪里得到的“单个u8值”-即使它是这样的,它也只是一个函数指针。
u8
是一个参数,在运行时传递给它,它不会是对象的一部分。函数指针和闭包在Rust中不兼容
这是部分正确的,但
Fn
不是函数指针。这里所指的是捕获闭包与fn
函数指针不兼容。事实上,每个闭包都实现了Fn
变体之一。这里简单回顾一下:
fn
-简单的函数指针。它对外部的引用为零,并且是完全独立的。Fn
-可以通过引用调用的函数类型。可以不变地捕获外部变量。FnMut
-可以通过可变引用调用的函数类型。可以不变地捕获外部变量。FnOnce
-一种只能由所有权调用的函数类型,它在调用时被消耗,因此只能调用一次。可以执行只能执行一次的操作(如可变消耗)。下面是一个非常全面的所有可能组合的例子: