簡體   English   中英

找不到類型為len的方法 <T as Trait> ::在當前范圍內輸入

[英]No method named len found for type <T as Trait>::Type in the current scope

我想通知VecLengthDirectorAbstractVecLengthBuider的關聯類型始終為[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);
   |                            ^^^^

我想通知VecLengthDirectorAbstractVecLengthBuider的關聯類型始終為[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()

然后,您只需要限制PointTypePointType上可迭代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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM