rust 当T需要实现为< f32>

kb5ga3dv  于 2023-05-07  发布在  其他
关注(0)|答案(2)|浏览(168)

所以我有下面的代码片段,我想接受任意值的Vec,并将这些值转换为f32。这是为了处理浮点数、整型数、无符号值等。

pub struct Vals {
    // Our concrete values
    mat: Vec<Vec<f32>>,
    shape: (usize, usize),
    name: String,
}

impl Vals {
    pub fn from_vec<T: Into<f32>>(vec: Vec<T>, name: Option<String>) -> Self {
        let s1 = vec.iter().len();
        let mut as_mat: Vec<Vec<f32>> = Vec::new();

        let recasted = vec.iter().map(|&x| x as f32).collect(); 

        as_mat.push(vec);

        Vals {
            mat: as_mat,
            shape: (s1, 1),
            name: name.unwrap_or(String::from("")),
        }
    }

我在下面这行遇到了一个问题:
let recasted = vec.iter().map(|&x| x as f32).collect();,它告诉我anexpression can only be used to convert between primitive types or to coerce to a specific trait object,但我认为我指定Into trait可以处理这个问题?
我已经通读了From and Into Rust Documentation,但似乎没有什么可以帮助我解决我的问题。我看到它提到了how to create itself from another type, hence providing a very simple mechanism for converting between several types,但我认为我可以处理这个。我主要是在寻找建议,要么重组我的代码,使之成为可能,或直接解决错误。
谢谢大家!
编辑:我根据@drewtato的建议重新构造了from_vec函数,现在有了

pub fn from_vec<T: Into<f32>>(vec: Vec<T>, name: Option<String>) -> Self {
        // `Vec` has a `len` method already
        let s1 = vec.len();
        let recasted = vec.into_iter().map(|x| x.into()).collect();
        // Don't need to create the empty `Vec`
        let mat = vec![recasted];

        Vals {
            mat,
            shape: (s1, 1),
            name: name.unwrap_or_default(),
        }
    }

但在我的测试案例中

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_vec(){
        let v1= vec![1,2,3];
        let res = Vals::from_vec(v1, None);
    }
}

但似乎并不像我想的那样我要

the trait bound `f32: std::convert::From<i32>` is not satisfied
[E0277] the trait `std::convert::From<i32>` is not implemented for 
`f32` Help: the following other types implement trait 
`std::convert::From<T>`: <f32 as std::convert::From<bool>> <f32 as 
std::convert::From<i16>> <f32 as std::convert::From<i8>> <f32 as 
std::convert::From<u16>> <f32 as std::convert::From<u8>> Note: 
required for `i32` to implement `std::convert::Into<f32>` Note: 
required for `f32` to implement `std::convert::TryFrom<i32>`

我不明白我阅读这篇文章是因为强制转换没有实现,但是如果我实现了强制转换,那不是违背了泛型的目的吗?

gc0ot86w

gc0ot86w1#

as是一个特殊的内建函数,可以转换原语和其他一些东西,但是它没有连接到任何trait,所以你不能在泛型上使用它。这与几乎所有其他操作符不同,它们都与trait相连。+对应于std::ops::Add trait,*std::ops::Deref trait,甚至for循环使用std::iter::IntoIterator trait。
Into是一个完全正常的trait,与任何操作符语法无关。作为一个trait,你可以用它来限制泛型,你已经做到了,然后在泛型值上使用它的方法。但它根本不知道as
要使用T: Into,您需要使用Into::into

let recasted = vec.into_iter().map(|x| x.into()).collect();

如果您希望能够接受任何可以用as转换的值,您可以使用num-traits crate,它提供了AsPrimitive trait。该trait仍然不知道as是什么,但它们有一个方法as_,该方法已经为每一个可能的转换实现,以在内部调用asx.as_()大致相当于x as _

use num_traits::AsPrimitive;

impl Vals {
    pub fn from_vec<T: AsPrimitive<f32>>(vec: Vec<T>, name: Option<String>) -> Self {
    ...
        let recasted = vec.into_iter().map(|x| x.as_()).collect();
    ...
    }
}

这与Into略有不同,因为您可以使用as而不是Intof64转换为f32,并且标准库之外的类型可能实现Into<f32>,但很少实现AsPrimitive
另一个错误是因为Into::into获取了它正在转换的值的所有权。对于实现了Copy的类型,比如数字原语,你可以直接解引用它们来获得一个拥有的值。您可以通过进一步限制泛型来使其在函数中工作。

pub fn from_vec<T: Into<f32> + Copy>

注意,如果你这样做,你应该take your parameter by reference

(vec: &[T], name: Option<String>)

另一种选择是,如果您希望能够接受不是Copy的值,则可以使用into_iter来始终拥有值。我在第一个片段中使用了它,这里再次使用。

let recasted = vec.into_iter().map(|x| x.into()).collect();

但是,这限制了您获得Vec的所有权,并且不能在其位置上使用&[T]
你还可以做一些直接等价的修改。这是整个函数的清理。

pub fn from_vec<T: Into<f32>>(vec: Vec<T>, name: Option<String>) -> Self {
    // `Vec` has a `len` method already
    let s1 = vec.len();
    let recasted = vec.into_iter().map(|x| x.into()).collect();
    // Don't need to create the empty `Vec`
    let mat = vec![recasted];

    Vals {
        // This is the same as `mat: mat,`
        mat,
        shape: (s1, 1),
        // The default of `String` is an empty string
        name: name.unwrap_or_default(),
    }
}
xt0899hw

xt0899hw2#

您可以使用into将值转换为f32

let recasted: Vec<f32> = vec.into_iter().map(|x| x.into()).collect();

相关问题