Methods 锈迹类型之谜:将函数转换为方法,并调用函数';s的签名中断编译

Methods 锈迹类型之谜:将函数转换为方法,并调用函数';s的签名中断编译,methods,types,rust,Methods,Types,Rust,一个关于锈菌类型的谜团,我不太明白 我最近正在为一个项目重构代码,遇到了一个输入错误 让我困惑不解的神秘,我希望这里的人能澄清真相 继续 我一直在给你写一个程序。“接缝雕刻” 是一种通过查找自动缩小图像尺寸的方法,例如 第一行中的每个像素,从 从上到下或从左到右,对车辆造成的损坏最小 然后移除该“接缝”。路径是从 每个像素的能量:该像素颜色之间的距离 计算两个邻域,然后计算总数最低的接缝 三角洲被识别 所以,形象→ 能量图→ 接缝→ 缩小图像 在内存中,图像是连接在一起的行的集合。 扫描垂直接缝

一个关于锈菌类型的谜团,我不太明白

我最近正在为一个项目重构代码,遇到了一个输入错误 让我困惑不解的神秘,我希望这里的人能澄清真相 继续

我一直在给你写一个程序。“接缝雕刻” 是一种通过查找自动缩小图像尺寸的方法,例如 第一行中的每个像素,从 从上到下或从左到右,对车辆造成的损坏最小 然后移除该“接缝”。路径是从 每个像素的能量:该像素颜色之间的距离 计算两个邻域,然后计算总数最低的接缝 三角洲被识别

所以,形象→ 能量图→ 接缝→ 缩小图像

在内存中,图像是连接在一起的行的集合。 扫描垂直接缝意味着扫描行(左侧和右侧 相邻区域形成三角形),但扫描水平接缝意味着 扫描列。列中的相邻像素在列中不相邻 内存,这使得多线程与人造丝或横梁 困难

好消息是每个源都是只读的。产生能量 map只需要对能量图进行写访问。对于专栏,如果我 可以旋转能量图,我可以多线程水平扫描。 这很简单,我只需要一个代理对象来映射 读取图像时,将
(x,y)
转换为
(y,x)
。让我们称之为代理 对象a
Pivot

让我展示一些代码(AviShaOne是第一个接缝雕刻算法, 来自Avidan&Shamir,“接缝雕刻”,2007年):

我所做的只是将
calculate_energy
移动到实现中。没有别的 代码已更改
Pivot
具有与AviShaOne相同的类型签名, 因为他们都在处理这些
GenericImageView
对象。现在呢 不会编译:

176 |         energy_to_seam(&self.calculate_energy(&Pivot::new(self.image)))
    |                                               ^^^^^^ expected type parameter, found struct `pivot::Pivot`
这是个谜。这些功能实际上是相同的。类型 据我所知,签名是一致的,字面上是复制的& 粘贴以保持一致性。我还没有将
能量
添加为一个字段!当函数只是一个简单的函数时,它工作得很好 函数,但现在它是实现的成员,编译器 我想要别的东西,但我不知道是什么


编译器想要什么?

有一个非常重要的变化,
calculate\u energy
不再是所有类型
I
的通用函数,因此
I:Gener…
等。相反,它是一个常规函数,需要非常特定的类型
I

哪种类型的
I
?好的,无论我使用哪个
I
AviShaOne
使用哪个,我假设它的类型与
self.image
相同。因此调用
calculate\u energy(self.image)
就可以了


但是,
Pivot::new(self.image)
有一个完全不同的类型,它是
Pivot
,而不是
I
。由于
calculate\u energy
不再是一个通用函数,它无法处理这个问题。

有一个非常重要的变化,
calculate\u energy
不再是所有类型
I
的通用函数,因此
I:Gener…
等,相反,它是一个常规函数,需要一个非常特定的类型
I

哪种类型的
I
?好的,无论我使用哪个
I
AviShaOne
使用哪个,我假设它的类型与
self.image
相同。因此调用
calculate\u energy(self.image)
就可以了


但是,
Pivot::new(self.image)
有一个完全不同的类型,它是
Pivot
,而不是
I
。由于
calculate\u energy
不再是一个通用函数,它无法处理这个问题。

Pivot的定义是什么?它是一个具有完全相同签名的结构,是
I
的完整实现。
Pivot
的定义是什么?它是一个具有完全相同签名和完整实现的结构这似乎有点违反直觉,因为
Pivot
I
的一个实现。如果错误信息更清楚,那就好了。我理解它为什么不工作,并且有一个可接受的解决方案(将能量映射保留在主结构中以进行缓存,但将其传递给函数以进行实际映射过程),但这似乎没有我预期的那么OO-y。(我知道,Rust不是一种OO语言,但有时候,
impl
s觉得应该是这样。)@ElfSternberg不,你还是有点困惑
Pivot
不是
I
的实现(这甚至不可能,
I
是一种具体类型,而不是特征),它是
GenericImageView
的实现。但是
calculate_energy
期望
I
,而不是
GenericImageView
,当您将其设置为非generic时。你可以把它放在类中,但要让它再次泛化,这是有道理的。我会看看是否可以将其泛化,也许这会帮助我理解其中的区别。这似乎有点违反直觉,因为
Pivot
I
的一个实现。如果错误信息更清楚,那就好了。我理解它为什么不工作,并且有一个可接受的解决方案(将能量映射保留在主结构中以进行缓存,但将其传递给函数以进行实际映射过程),但这似乎没有我预期的那么OO-y。(我知道,Rust不是一种OO语言,但有时候,
impl
s觉得应该是这样。)@ElfSternberg不,你还是有点困惑
Pivot
不是
I
的实现(这甚至不可能,
I
是一种具体类型,而不是特征),它是
GenericImageView
的实现。但是
calculate_energy
期望
I
,而不是
一般图像视图
impl<'a, I, P, S>  AviShaOne<'a, I, P, S>
where
    I: GenericImageView<Pixel = P>,
    P: Pixel<Subpixel = S> + 'static,
    S: Primitive + 'static,
{
    fn calculate_energy(&self, image: &I) -> TwoDimensionalMap<u32>
    {
        ...
    }

    fn find_horizontal_seam(&self) -> Vec<u32> {
        energy_to_seam(&self.calculate_energy(&Pivot::new(self.image)))
    }
}
176 |         energy_to_seam(&self.calculate_energy(&Pivot::new(self.image)))
    |                                               ^^^^^^ expected type parameter, found struct `pivot::Pivot`