Rust:无法将 Trait RangeBounds 制成对象
Rust: Trait RangeBounds cannot be made into an object
我在尝试 Rust 时偶然发现了一个问题,这可能表明我对它的概念有更大的不理解。
我的目标是编写康威生命游戏的一个变体。我希望单元格创建或保持活动时的值不是硬编码的,而是在结构中。我的第一次尝试是创建一个结构
use std::ops::Range;
struct Rules {
be_born: Range<usize>,
stay_alive: Range<usize>,
}
impl Rules {
pub fn new(be_born: Range<usize>, stay_alive: Range<usize>) -> Rules {
Rules { be_born, stay_alive }
}
}
let rules = Rules::new(2..4, 3..6);
此对象稍后在迭代所有单元格的算法中使用。它工作正常,直到我还想在创建过程中允许其他类型的范围,例如 RangeTo (2..=3).
我知道我可以将 struct Rules
重写为通用的。
use std::ops::RangeBounds;
struct Rules<BR: RangeBounds<usize>, AR: RangeBounds<usize>> {
be_born: BR,
stay_alive: AR,
}
这反过来又会迫使我使我使用的所有算法也通用。这似乎是相当多的开销,只是为了包括两个简单的范围。
另一方面,我 none 尝试将 RangeBounds
类型的变量直接包含到我的结构中的尝试成功了。我尝试了 &dyn RangeBounds<usize>
或 Box<&dyn RangeBounds<usize>>
,只是总是得到错误 E0038,我无法将这个特征变成一个对象。
是否有任何其他方法可以完成此操作,或者是否有其他一些我没有看到的可行方法?
预先感谢您的所有提示。
为了获得广泛的答案,我们需要知道您在 be_born
和 stay_alive
字段上迭代的准确程度。但是为了解决您指出要使用不同类型范围的问题,最简单的方法是指定 be_born
和 stay_alive
字段都是 Iterable
和 returns usize
迭代时,又名 Iterator<Item=usize>
:
struct Rules<T, U>
where
T: Iterator<Item=usize>,
U: Iterator<Item=usize>
{
be_born: T,
stay_alive: U,
}
impl<T, U> Rules<T, U>
where
T: Iterator<Item=usize>,
U: Iterator<Item=usize>
{
pub fn new(be_born: T, stay_alive: U) -> Self {
Self { be_born, stay_alive }
}
}
fn main() {
let rule = Rules::new(2..4, 3..6);
let other_rule = Rules::new(2..=4, 3..=6);
let another_rule = Rules::new(2..=4, 3..6);
for x in rule.be_born {
println!("born: {}", x);
}
for y in rule.stay_alive {
println!("alive: {}", y);
}
}
这也将允许您将非范围但可迭代的类型分配给 be_born
和 stay_alive
字段。如果您只想限制范围类型,您可以将代码中的每个 Iterator<Item=usize>
替换为 Iterator<Item=usize> + RangeBounds<usize>
,这意味着“一种同时实现 Iterator<Item=usize>
和 RangeBounds<usize>
的类型” .
有关 Iterator
特性的进一步用法,请参阅 the book。
我在尝试 Rust 时偶然发现了一个问题,这可能表明我对它的概念有更大的不理解。
我的目标是编写康威生命游戏的一个变体。我希望单元格创建或保持活动时的值不是硬编码的,而是在结构中。我的第一次尝试是创建一个结构
use std::ops::Range;
struct Rules {
be_born: Range<usize>,
stay_alive: Range<usize>,
}
impl Rules {
pub fn new(be_born: Range<usize>, stay_alive: Range<usize>) -> Rules {
Rules { be_born, stay_alive }
}
}
let rules = Rules::new(2..4, 3..6);
此对象稍后在迭代所有单元格的算法中使用。它工作正常,直到我还想在创建过程中允许其他类型的范围,例如 RangeTo (2..=3).
我知道我可以将 struct Rules
重写为通用的。
use std::ops::RangeBounds;
struct Rules<BR: RangeBounds<usize>, AR: RangeBounds<usize>> {
be_born: BR,
stay_alive: AR,
}
这反过来又会迫使我使我使用的所有算法也通用。这似乎是相当多的开销,只是为了包括两个简单的范围。
另一方面,我 none 尝试将 RangeBounds
类型的变量直接包含到我的结构中的尝试成功了。我尝试了 &dyn RangeBounds<usize>
或 Box<&dyn RangeBounds<usize>>
,只是总是得到错误 E0038,我无法将这个特征变成一个对象。
是否有任何其他方法可以完成此操作,或者是否有其他一些我没有看到的可行方法?
预先感谢您的所有提示。
为了获得广泛的答案,我们需要知道您在 be_born
和 stay_alive
字段上迭代的准确程度。但是为了解决您指出要使用不同类型范围的问题,最简单的方法是指定 be_born
和 stay_alive
字段都是 Iterable
和 returns usize
迭代时,又名 Iterator<Item=usize>
:
struct Rules<T, U>
where
T: Iterator<Item=usize>,
U: Iterator<Item=usize>
{
be_born: T,
stay_alive: U,
}
impl<T, U> Rules<T, U>
where
T: Iterator<Item=usize>,
U: Iterator<Item=usize>
{
pub fn new(be_born: T, stay_alive: U) -> Self {
Self { be_born, stay_alive }
}
}
fn main() {
let rule = Rules::new(2..4, 3..6);
let other_rule = Rules::new(2..=4, 3..=6);
let another_rule = Rules::new(2..=4, 3..6);
for x in rule.be_born {
println!("born: {}", x);
}
for y in rule.stay_alive {
println!("alive: {}", y);
}
}
这也将允许您将非范围但可迭代的类型分配给 be_born
和 stay_alive
字段。如果您只想限制范围类型,您可以将代码中的每个 Iterator<Item=usize>
替换为 Iterator<Item=usize> + RangeBounds<usize>
,这意味着“一种同时实现 Iterator<Item=usize>
和 RangeBounds<usize>
的类型” .
有关 Iterator
特性的进一步用法,请参阅 the book。