我有一个结构,主要封装了一个向量:
struct Group<S> {
elements: Vec<S>
}
Run Code Online (Sandbox Code Playgroud)
我也有一个简单的特征,该特征也可用于其他结构:
trait Solid {
fn intersect(&self, ray: f32) -> f32;
}
Run Code Online (Sandbox Code Playgroud)
我想实现Solid的Group,但我希望能够使用Group都为相同的实现的名单Solid和混合实现的名单Solid。基本上我想同时使用Group<Box<Solid>>和Group<Sphere>(Sphere实现Solid)。
目前我正在使用这样的东西:
impl Solid for Group<Box<Solid>> {
fn intersect(&self, ray: f32) -> f32 {
//do stuff
}
}
impl<S: Solid> Solid for Group<S> {
fn intersect(&self, ray: f32) -> f32 {
//do the same stuff, code copy-pasted from previous impl
}
}
Run Code Online (Sandbox Code Playgroud)
这是可行的,但是两次换行相同的代码不是惯用的解决方案。我一定缺少明显的东西吗?
就我而言,我测量了两个特征实现之间的显着性能差异,因此始终使用Group<Box<Solid>>不是一个好选择。
在实现您特质的所有Box<S>地方S实施您的特质。然后,您只需委托给现有实现即可:
impl<S: Solid + ?Sized> Solid for Box<S> {
fn intersect(&self, ray: f32) -> f32 {
(**self).intersect(ray)
}
}
Run Code Online (Sandbox Code Playgroud)
您还将发现对参考进行相同的操作可能很有用:
impl<'a, S: Solid + ?Sized> Solid for &'a S {
fn intersect(&self, ray: f32) -> f32 {
(**self).intersect(ray)
}
}
Run Code Online (Sandbox Code Playgroud)
全部一起:
trait Solid {
fn intersect(&self, ray: f32) -> f32;
}
impl<S: Solid + ?Sized> Solid for Box<S> {
fn intersect(&self, ray: f32) -> f32 {
(**self).intersect(ray)
}
}
impl<'a, S: Solid + ?Sized> Solid for &'a S {
fn intersect(&self, ray: f32) -> f32 {
(**self).intersect(ray)
}
}
struct Group<S>(Vec<S>);
impl<S: Solid> Solid for Group<S> {
fn intersect(&self, ray: f32) -> f32 {
42.42
}
}
struct Point;
impl Solid for Point {
fn intersect(&self, ray: f32) -> f32 {
100.
}
}
fn main() {
let direct = Group(vec![Point]);
let boxed = Group(vec![Box::new(Point)]);
let pt = Point;
let reference = Group(vec![&pt]);
let mixed: Group<Box<Solid>> = Group(vec![
Box::new(direct),
Box::new(boxed),
Box::new(Point),
Box::new(reference),
]);
mixed.intersect(1.0);
}
Run Code Online (Sandbox Code Playgroud)
该?Sized绑定允许S不具有在编译时已知的大小。重要的是,这允许您传入特征对象,例如Box<Solid>或&Solid类型Solid不具有已知大小的对象。
| 归档时间: |
|
| 查看次数: |
783 次 |
| 最近记录: |