如何让 Rust Generic Struct/Trait 需要一个 Box<other trait>?
How to make a Rust Generic Struct/Trait require a Box<other trait>?
我有一个特征 Agent
表示模拟中的代理,以及一个实现此特征的结构 SimpleAgent
。由于 Agent
的大小在编译时未知,我的代码通常使用 Vec<Box<dyn Agent>>
我想创建一个通用特征 AgentCollection<T>
并使用 AgentTree<T>
结构实现它。
到目前为止我有以下内容:
pub trait AgentCollection<T> {
fn new(agents: Vec<Box<T>>) -> Self;
fn get_in_rectilinear_range(point: vec::Vec2, range: f64) -> Vec<Box<T>>;
fn get_in_euclidean_range(point: vec::Vec2, range: f64) -> Vec<Box<T>>;
}
pub struct AgentTree<T: agent::Agent> {
left: Option<Box<AgentTree<T>>>,
right: Option<Box<AgentTree<T>>>,
node: Box<T>,
}
#[allow(unused)]
impl<T: agent::Agent> AgentTree<T> {
fn range_search(point: vec::Vec2, range: f64) -> std::vec::Vec<Box<T>> {
todo!()
}
}
impl<T: agent::Agent> AgentCollection<T> for AgentTree<T> {
fn new(agents: std::vec::Vec<Box<T>>) -> Self {
todo!()
}
fn get_in_rectilinear_range(point: vec::Vec2, range: f64) -> std::vec::Vec<Box<T>> {
todo!()
}
fn get_in_euclidean_range(point: vec::Vec2, range: f64) -> std::vec::Vec<Box<T>> {
todo!()
}
}
这都是类型检查。但是,当我在主文件中使用它时,例如
let agent_tree = AgentTree::new(last_agents);
其中 last_agents
的类型为 std::vec::Vec<std::boxed::Box<dyn agent::Agent>>
,我得到错误 the size for values of type 'dyn agent::Agent' cannot be known at compilation time
。
我想我想以某种方式将 AgentTree
类型参数限制为 Box<agent::Agent
而不仅仅是 agent::Agent
,以便调整大小,但我不知道如何去做。我试过例如:pub struct AgentTree<T: Box<agent::Agent>> { ... }
.
想通了,我添加了以下内容:
type BoxedAgent = Box<dyn agent::Agent>;
然后用BoxedAgent
代替Box<T: agent::Agent>
。
暂时搁置此问题,以防有人有更好的建议。
默认情况下,泛型类型参数将有一个 Sized
需要大小类型的特征边界。但是像 dyn Agent
这样的特征对象没有大小,它们可以表示多种类型,因此在编译时无法知道它们的大小。
要使您的代码与 dyn Agent
一起工作,您所要做的就是在特征范围中添加 ?Sized
以删除默认的 Sized
特征范围:
pub trait AgentCollection<T: ?Sized> {
// ^^^^^^
fn new(agents: Vec<Box<T>>) -> Self;
fn get_in_rectilinear_range(point: vec::Vec2, range: f64) -> Vec<Box<T>>;
fn get_in_euclidean_range(point: vec::Vec2, range: f64) -> Vec<Box<T>>;
}
pub struct AgentTree<T: ?Sized + agent::Agent> {
// ^^^^^^
left: Option<Box<AgentTree<T>>>,
right: Option<Box<AgentTree<T>>>,
node: Box<T>,
}
#[allow(unused)]
impl<T: ?Sized + agent::Agent> AgentTree<T> {
// ^^^^^^
fn range_search(point: vec::Vec2, range: f64) -> std::vec::Vec<Box<T>> {
todo!()
}
}
impl<T: ?Sized + agent::Agent> AgentCollection<T> for AgentTree<T> {
// ^^^^^^
fn new(agents: std::vec::Vec<Box<T>>) -> Self {
todo!()
}
fn get_in_rectilinear_range(point: vec::Vec2, range: f64) -> std::vec::Vec<Box<T>> {
todo!()
}
fn get_in_euclidean_range(point: vec::Vec2, range: f64) -> std::vec::Vec<Box<T>> {
todo!()
}
}
我有一个特征 Agent
表示模拟中的代理,以及一个实现此特征的结构 SimpleAgent
。由于 Agent
的大小在编译时未知,我的代码通常使用 Vec<Box<dyn Agent>>
我想创建一个通用特征 AgentCollection<T>
并使用 AgentTree<T>
结构实现它。
到目前为止我有以下内容:
pub trait AgentCollection<T> {
fn new(agents: Vec<Box<T>>) -> Self;
fn get_in_rectilinear_range(point: vec::Vec2, range: f64) -> Vec<Box<T>>;
fn get_in_euclidean_range(point: vec::Vec2, range: f64) -> Vec<Box<T>>;
}
pub struct AgentTree<T: agent::Agent> {
left: Option<Box<AgentTree<T>>>,
right: Option<Box<AgentTree<T>>>,
node: Box<T>,
}
#[allow(unused)]
impl<T: agent::Agent> AgentTree<T> {
fn range_search(point: vec::Vec2, range: f64) -> std::vec::Vec<Box<T>> {
todo!()
}
}
impl<T: agent::Agent> AgentCollection<T> for AgentTree<T> {
fn new(agents: std::vec::Vec<Box<T>>) -> Self {
todo!()
}
fn get_in_rectilinear_range(point: vec::Vec2, range: f64) -> std::vec::Vec<Box<T>> {
todo!()
}
fn get_in_euclidean_range(point: vec::Vec2, range: f64) -> std::vec::Vec<Box<T>> {
todo!()
}
}
这都是类型检查。但是,当我在主文件中使用它时,例如
let agent_tree = AgentTree::new(last_agents);
其中 last_agents
的类型为 std::vec::Vec<std::boxed::Box<dyn agent::Agent>>
,我得到错误 the size for values of type 'dyn agent::Agent' cannot be known at compilation time
。
我想我想以某种方式将 AgentTree
类型参数限制为 Box<agent::Agent
而不仅仅是 agent::Agent
,以便调整大小,但我不知道如何去做。我试过例如:pub struct AgentTree<T: Box<agent::Agent>> { ... }
.
想通了,我添加了以下内容:
type BoxedAgent = Box<dyn agent::Agent>;
然后用BoxedAgent
代替Box<T: agent::Agent>
。
暂时搁置此问题,以防有人有更好的建议。
默认情况下,泛型类型参数将有一个 Sized
需要大小类型的特征边界。但是像 dyn Agent
这样的特征对象没有大小,它们可以表示多种类型,因此在编译时无法知道它们的大小。
要使您的代码与 dyn Agent
一起工作,您所要做的就是在特征范围中添加 ?Sized
以删除默认的 Sized
特征范围:
pub trait AgentCollection<T: ?Sized> {
// ^^^^^^
fn new(agents: Vec<Box<T>>) -> Self;
fn get_in_rectilinear_range(point: vec::Vec2, range: f64) -> Vec<Box<T>>;
fn get_in_euclidean_range(point: vec::Vec2, range: f64) -> Vec<Box<T>>;
}
pub struct AgentTree<T: ?Sized + agent::Agent> {
// ^^^^^^
left: Option<Box<AgentTree<T>>>,
right: Option<Box<AgentTree<T>>>,
node: Box<T>,
}
#[allow(unused)]
impl<T: ?Sized + agent::Agent> AgentTree<T> {
// ^^^^^^
fn range_search(point: vec::Vec2, range: f64) -> std::vec::Vec<Box<T>> {
todo!()
}
}
impl<T: ?Sized + agent::Agent> AgentCollection<T> for AgentTree<T> {
// ^^^^^^
fn new(agents: std::vec::Vec<Box<T>>) -> Self {
todo!()
}
fn get_in_rectilinear_range(point: vec::Vec2, range: f64) -> std::vec::Vec<Box<T>> {
todo!()
}
fn get_in_euclidean_range(point: vec::Vec2, range: f64) -> std::vec::Vec<Box<T>> {
todo!()
}
}