[英]No method named len found for type <T as Trait>::Type in the current scope
我想通知VecLengthDirector
, AbstractVecLengthBuider
的關聯類型始終為[i32; n]
[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);
| ^^^^
我想通知
VecLengthDirector
,AbstractVecLengthBuider
的關聯類型始終為[i32; n]
[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;
在特征定義中。
快速解決
您需要指定PointType
的類型。 例如T: AbstractVecLengthBuider<PointType = [i32]>>
。 但是, [i32]
的大小在編譯時未知,因此可以將其替換為Vec<i32>
: T: AbstractVecLengthBuider<PointType = Vec<i32>>
。
如果你仍然想是通用的,可以約束PointType
是borrowable為[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方式
您的循環可以重寫為更慣用的Rust:
s.iter()
.zip(e.iter())
.map(|(se, ee)| (se - ee).pow(2) as f64)
.sum()
然后,您只需要限制PointType
在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()
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.