Generics 如何为任何元素序列实现特征?

Generics 如何为任何元素序列实现特征?,generics,rust,iterator,traits,Generics,Rust,Iterator,Traits,我试图为任何元素序列实现一个trait,这样它就可以用于向量、数组和切片。到目前为止,我已经尝试了几种方法,但都无法编译:( 我有这个特性,有一个使用它的函数,还有一个实现该特性的基本数据类型: trait Hitable { fn hit(&self, val: f64) -> bool; } fn check_hit<T: Hitable>(world: &T) -> bool { world.hit(1.0) } struct O

我试图为任何元素序列实现一个trait,这样它就可以用于向量、数组和切片。到目前为止,我已经尝试了几种方法,但都无法编译:(

我有这个特性,有一个使用它的函数,还有一个实现该特性的基本数据类型:

trait Hitable {
    fn hit(&self, val: f64) -> bool;
}

fn check_hit<T: Hitable>(world: &T) -> bool {
    world.hit(1.0)
}

struct Obj(f64);

impl Hitable for Obj {
    fn hit(&self, val: f64) -> bool {
        self.0 > val
    }
}
但是我想让它更通用,这样它就可以用于数组和切片;我该怎么做呢

我尝试了以下四种尝试:

尝试#1:用于Hitables上的迭代器。
//不清楚如何调用它:
//无法编译vec.iter().hit(…)
//无法编译vec.into_iter().hit(…)
//
对于T而言,完全可以命中
哪里
T:迭代器,
U:Hitable,
{
fn命中(&self,val:f64)->bool{
self.any(|h | h.hit(val))
}
}
尝试#2:寻找可以转化为迭代器的东西。
//也不编译:
//
//self.into_iter().any(|h | h.hit(val))
//^^^^无法移出借用的内容
//
对于T而言,完全可以命中
哪里
T:迭代器,
U:Hitable,
{
fn命中(&self,val:f64)->bool{
self.into_iter().any(|h | h.hit(val))
}
}
尝试#3:用于切片。
//此用法无法编译:
//设v=vec![Obj(2.0),Obj(3.0)];
//println!(“{}”,勾选[u hit(&v));
//
//它说Hitable不是为向量实现的。
//当我将向量转换为切片时,即&v[…],抱怨
//编译时大小未知。
对于[T]而言,可点击
哪里
T:Hitable,
{
fn命中(&self,val:f64)->bool{
self.iter().any(|h | h.hit(val))
}
}
尝试#4:对于迭代器+克隆
//让v=vec![Obj(2.0),Obj(3.0)];
//println!(“{}”,check_hit(&v.iter());
//
//不编译:
//println!(“{}”,check_hit(&v.iter());
//^^^^`&Obj`不是迭代器
//
对于T而言,完全可以命中
哪里
T:迭代器+克隆,
U:Hitable,
{
fn命中(&self,val:f64)->bool{
self.clone().any(|h | h.hit(val))
}
}

1.
迭代器
基于 这是不可行的,因为迭代器需要是可变的,以提高它们的性能,但您的特性需要
和self

2.
IntoIterator
-基于 我将trait更改为按值获取
self
,然后仅对
Obj
的引用实现它。这也允许对任何实现
到迭代器的类型实现它:

trait Hitable {
    fn hit(self, val: f64) -> bool;
}

fn check_hit<T: Hitable>(world: T) -> bool {
    world.hit(1.0)
}

struct Obj(f64);

impl Hitable for &'_ Obj {
    fn hit(self, val: f64) -> bool {
        self.0 > val
    }
}

impl<I> Hitable for I
where
    I: IntoIterator,
    I::Item: Hitable,
{
    fn hit(self, val: f64) -> bool {
        self.into_iter().any(|h| h.hit(val))
    }
}

fn main() {
    let o = Obj(2.0);
    let v = vec![Obj(2.0), Obj(3.0)];

    println!("{}", check_hit(&o));
    println!("{}", check_hit(&v));
}
另见:


&self
-您是否知道Rust中的可变性概念,以及
迭代器::next
需要一个可变接收器的事实?
可用于T
&self
-您是否意识到对类型的引用可能实现与类型本身不同的特性?@Shepmaster是的,我想我理解这一点se概念。我的trait不需要改变基础值,所以在迭代器上实现它可能不是一个好主意。关于你的第二点:我不太确定当我为某些引用类型&t实现trait时,trait的函数参数&self会发生什么情况。它会是&t吗?我应该取消引用它吗?我在trait中使用&self函数显示我只需要读访问(无所有权,无变异)…,这里的工作版本为into_iter()和iter()。它与@Shepmaster指出的可变性有关。@ÖmerErden是的,谢谢,它现在确实有效。但是,现在当我意识到为迭代器实现它需要变异时,我认为最好只在切片上实现它,因为trait函数不需要变异(它只读取数据)。太好了,谢谢!是的,我看到了错误消息,甚至检查了建议的链接。但是,我不知道我到底需要在哪里添加
?size
,出于某种原因,我认为我必须在trait实现中将其添加到边界中(我尝试了,但没有帮助)。这种方法(即在片上实现trait)吗“被认为是完成这样一项任务的最佳方案吗?”@Diing_sphynx我不知道“最佳方案”是什么。我认为两种可行的解决方案都是合理的。
// It's not clear how to call it:
//    vec.iter().hit(...) does not compile
//    vec.into_iter().hit(...) does not compile
//
impl<T, U> Hitable for T
where
    T: Iterator<Item = U>,
    U: Hitable,
{
    fn hit(&self, val: f64) -> bool {
        self.any(|h| h.hit(val))
    }
}
// Does not compile as well:
//
//         self.into_iter().any(|h| h.hit(val))
//         ^^^^ cannot move out of borrowed content
//
impl<T, U> Hitable for T
where
    T: IntoIterator<Item = U>,
    U: Hitable,
{
    fn hit(&self, val: f64) -> bool {
        self.into_iter().any(|h| h.hit(val))
    }
}
// This usage doesn't compile:
//     let v = vec![Obj(2.0), Obj(3.0)];
//     println!("{}", check_hit(&v));
//
// It says that Hitable is not implemented for vectors.
// When I convert vector to slice, i.e. &v[..], complains about
// unknown size in compilation time.
impl<T> Hitable for [T]
where
    T: Hitable,
{
    fn hit(&self, val: f64) -> bool {
        self.iter().any(|h| h.hit(val))
    }
}
//     let v = vec![Obj(2.0), Obj(3.0)];
//     println!("{}", check_hit(&v.iter()));
//
// does not compile:
//     println!("{}", check_hit(&v.iter()));
//                    ^^^^^^^^^ `&Obj` is not an iterator
//
impl<T, U> Hitable for T
where
    T: Iterator<Item = U> + Clone,
    U: Hitable,
{
    fn hit(&self, val: f64) -> bool {
        self.clone().any(|h| h.hit(val))
    }
}
trait Hitable {
    fn hit(self, val: f64) -> bool;
}

fn check_hit<T: Hitable>(world: T) -> bool {
    world.hit(1.0)
}

struct Obj(f64);

impl Hitable for &'_ Obj {
    fn hit(self, val: f64) -> bool {
        self.0 > val
    }
}

impl<I> Hitable for I
where
    I: IntoIterator,
    I::Item: Hitable,
{
    fn hit(self, val: f64) -> bool {
        self.into_iter().any(|h| h.hit(val))
    }
}

fn main() {
    let o = Obj(2.0);
    let v = vec![Obj(2.0), Obj(3.0)];

    println!("{}", check_hit(&o));
    println!("{}", check_hit(&v));
}
fn check_hit<T: Hitable + ?Sized>(world: &T) -> bool {
//                      ^~~~~~~~
    world.hit(1.0)
}