Rust:属性范围边界不能成为对象



我在尝试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,
}

这反过来会迫使我把我使用的所有算法都变成通用的。仅仅包括两个简单的范围,这似乎是相当大的开销。

另一方面,我尝试将类型为RangeBounds的变量直接包含到结构中的操作都没有成功。我尝试了&dyn RangeBounds<usize>Box<&dyn RangeBounds<usize>>,只是为了总是得到错误E0038,即我无法将此特性转化为对象。

有没有其他方法可以做到这一点,或者有没有其他我看不到的可行方法?

提前感谢你的所有提示。

要得到一个大致的答案,我们需要知道您在be_bornstay_alive字段上的迭代方式。但是,为了解决您指出要使用不同类型的范围的问题,最简单的方法是指定be_bornstay_alive字段都是Iterable,在迭代时返回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_bornstay_alive字段分配非范围但可迭代的类型。如果您只想将自己限制为范围类型,您可以将代码中的每个Iterator<Item=usize>都替换为Iterator<Item=usize> + RangeBounds<usize>,这意味着"同时实现CCD_ 16和CCD_;。

有关Iterator特性的进一步用法,请参阅本书。

最新更新