如何在Rust中创建可确定大小的函数Trait?解决动态类型大小报错
Rust 动态 trait 对象大小问题及解决思路
问题分析
你遇到的错误核心在于:dyn SimpleSpawner 是动态大小类型(DST),Rust 在编译时无法确定它的大小,而 Vec<T> 要求元素类型 T 必须是编译期大小确定的类型(即实现 Sized trait)。
你在 trait 中添加 Sized 约束的思路不成立——dyn Trait 形式的动态对象本身就不满足 Sized,即使 trait 要求 Sized,也无法让动态对象符合要求。另外,函数指针(fn(...) -> ...)是固定大小的,但它只能兼容无捕获的闭包,无法处理需要捕获环境的闭包,这也是你想要混用函数指针和闭包的矛盾点。
解决方案
下面提供几种可行的解决方式,你可以根据需求选择:
1. 使用 Box 包裹动态 trait 对象(推荐,兼顾灵活性和兼容性)
通过 Box<dyn SimpleSpawner> 将动态对象包装成胖指针(大小固定,包含函数指针和环境数据),这样就能满足 Vec 的 Sized 要求,同时支持函数指针和任意闭包:
#[derive(Clone)] pub struct RandomTable<T> { pub entries: Vec<T>, } impl<T> RandomTable<T> { pub fn new() -> Self { RandomTable { entries: Vec::new(), } } } // 去掉 trait 上的 Sized 约束,允许生成动态对象 pub trait SimpleSpawner: Fn(&mut u8) -> u8 {} // 为所有符合 Fn(&mut u8) -> u8 的类型自动实现 SimpleSpawner impl<F: Fn(&mut u8) -> u8> SimpleSpawner for F {} pub fn room_table(map_depth: i32) -> RandomTable<Box<dyn SimpleSpawner>> { RandomTable::new() }
使用示例:
fn example_spawner(x: &mut u8) -> u8 { *x += 1; *x } let mut table = room_table(1); // 添加函数指针 table.entries.push(Box::new(example_spawner)); // 添加捕获环境的闭包 let y = 5; table.entries.push(Box::new(move |x: &mut u8| *x + y));
2. 使用泛型函数返回具体类型
如果不需要动态多态,只需要针对特定类型生成表,可以用泛型:
#[derive(Clone)] pub struct RandomTable<T> { pub entries: Vec<T>, } impl<T> RandomTable<T> { pub fn new() -> Self { RandomTable { entries: Vec::new(), } } } pub trait SimpleSpawner: Fn(&mut u8) -> u8 {} impl<F: Fn(&mut u8) -> u8> SimpleSpawner for F {} // 返回具体类型的 RandomTable pub fn room_table<T: SimpleSpawner>(map_depth: i32) -> RandomTable<T> { RandomTable::new() }
这种方式没有动态分配的开销,但灵活性较差,每次调用都需要明确或推导 T 的类型。
3. 仅使用函数指针(无需闭包时)
如果你的场景不需要捕获环境的闭包,直接用函数指针类型即可:
#[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(&mut u8) -> u8; pub fn room_table(map_depth: i32) -> RandomTable<SimpleSpawner> { RandomTable::new() }
这种方式只能添加无捕获的函数或闭包,无法处理需要捕获环境的闭包。
内容的提问来源于stack exchange,提问作者bbarker
相关产品推荐
相关产品推荐

