我想通知VecLengthDirector
AbstractVecLengthBuider
的关联类型始终为[i32; n]
(n∈N)。我写了以下代码:
struct VecLengthDirector<T> {
builder: T,
}
impl<T> VecLengthDirector<T>
where
T: AbstractVecLengthBuider,
{
fn construct(&self) -> f64 {
let s = self.builder.get_start_point();
let e = self.builder.get_end_point();
let mut sum: i32 = 0;
for i in 0..s.len() {
sum += (s[i] - e[i]).pow(2);
}
(sum as f64).sqrt()
}
}
trait AbstractVecLengthBuider {
type PointType;
fn add_start_point(&mut self, point: Self::PointType);
fn get_start_point(&self) -> Self::PointType;
fn add_end_point(&mut self, point: Self::PointType);
fn get_end_point(&self) -> Self::PointType;
}
报告的错误。
error[E0599]: no method named `len` found for type `<T as AbstractVecLengthBuider>::PointType` in the current scope
--> src/main.rs:14:23
|
14 | for i in 0..s.len() {
| ^^^
error[E0608]: cannot index into a value of type `<T as AbstractVecLengthBuider>::PointType`
--> src/main.rs:15:21
|
15 | sum += (s[i] - e[i]).pow(2);
| ^^^^
error[E0608]: cannot index into a value of type `<T as AbstractVecLengthBuider>::PointType`
--> src/main.rs:15:28
|
15 | sum += (s[i] - e[i]).pow(2);
| ^^^^
答案 0 :(得分:1)
我想通知
VecLengthDirector
AbstractVecLengthBuider
的关联类型总是[i32; n]
(n∈N)。
你不能。如果要对关联类型使用特定操作,则需要使用一个或多个特征约束。
例如,索引需要实现Index
特征。
没有包含<[_]>::len
的特征。也就是说,您可以通过滥用迭代器来编写一个应该涵盖大多数相关案例的文章:
pub trait Length {
fn len(self) -> usize;
}
impl<'a, T> Length for &'a T
where
&'a T: IntoIterator,
<&'a T as IntoIterator>::IntoIter: ::std::iter::ExactSizeIterator,
{
fn len(self) -> usize {
self.into_iter().len()
}
}
pub trait RefLength {
fn len(&self) -> usize;
}
impl<T> RefLength for T
where
for<'a> &'a T: Length,
{
fn len(&self) -> usize {
Length::len(self)
}
}
然后,你可以在特质定义中使用类似type PointType: Index<usize> + RefLength;
的东西。
答案 1 :(得分:1)
<强>的QuickFix 强>
您需要指定PointType
的种类。例如T: AbstractVecLengthBuider<PointType = [i32]>>
。但是,[i32]
的大小在编译时是未知的,因此您可以将其替换为Vec<i32>
:T: AbstractVecLengthBuider<PointType = Vec<i32>>
。
如果您仍想要通用,则可以将PointType
限制为[i32]
可借用:
impl<T, P> VecLengthDirector<T>
where
T: AbstractVecLengthBuider<PointType = P>,
P: ::std::borrow::Borrow<[i32]>,
{
fn construct(&self) -> f64 {
let s = self.builder.get_start_point().borrow();
let e = self.builder.get_end_point().borrow();
// ...
}
}
这不是惯用的Rust。
惯用生锈方式
您的循环可以重写为更惯用的Rust:
s.iter()
.zip(e.iter())
.map(|(se, ee)| (se - ee).pow(2) as f64)
.sum()
然后你只需要约束PointType
可以在i32
上进行迭代:
impl<T, P> VecLengthDirector<T>
where
T: AbstractVecLengthBuider<PointType = P>,
P: ::std::iter::IntoIterator<Item = i32>,
{
fn construct(&self) -> f64 {
let s = self.builder.get_start_point();
let e = self.builder.get_end_point();
s.into_iter()
.zip(e.into_iter())
.map(|(se, ee)| (se - ee).pow(2) as f64)
.sum::<f64>()
.sqrt()
}
}