gpt4 book ai didi

rust - 如何修改我的构造函数以接受切片或对数组或向量的引用

转载 作者:行者123 更新时间:2023-11-29 08:03:38 24 4
gpt4 key购买 nike

这是我的代码的一个简化示例:

#[derive(Debug, Clone, Copy)]
enum Data<'a> {
I32(&'a [i32]),
F64(&'a [f64]),
}

impl<'a> From<&'a [i32]> for Data<'a> {
fn from(v: &'a [i32]) -> Data<'a> {
Data::I32(v)
}
}

impl<'a> From<&'a [f64]> for Data<'a> {
fn from(v: &'a [f64]) -> Data<'a> {
Data::F64(v)
}
}

#[derive(Debug, Clone, Copy)]
struct DataVar<'a> {
name: &'a str,
data: Data<'a>,
}

impl<'a> DataVar<'a> {
fn new<T>(name: &'a str, data: T) -> Self
where
T: Into<Data<'a>>,
{
Self {
name,
data: data.into(),
}
}
}

首先,考虑到我需要将不同的 DataVar 转换为同一个向量,并且我想避免使用特征对象,您认为我的实现是否正确或者您有什么建议需要改进吗?

现在是我的主要问题。我可以定义传递切片的新 DataVar,例如如下:

let x = [1, 2, 3];
let xvar = DataVar::new("x", &x[..]);

如何修改我的构造函数,使其不仅适用于切片,还适用于对数组或向量的引用?例如,我希望以下内容也能正常工作:

let x = [1, 2, 3];
let xvar = DataVar::new("x", &x);

编辑:

现在我尝试使用 trait 对象而不是枚举来实现相同的代码,但结果更糟......真的没有任何解决方案吗?

trait Data: std::fmt::Debug {}

impl Data for &[i32] {}

impl Data for &[f64] {}

#[derive(Debug, Clone, Copy)]
struct DataVar<'a> {
name: &'a str,
data: &'a dyn Data,
}

impl<'a> DataVar<'a> {
fn new<T>(name: &'a str, data: &'a T) -> Self
where
T: Data,
{
Self { name, data }
}
}

let x = [1, 2, 3];
let xvar = DataVar::new("x", &&x[..]);

最佳答案

对我来说,AsRef似乎不是正确的抽象有两个原因:首先,因为一个类型有可能(如果不太可能)同时实现 AsRef<[i32]>AsRef<[f64]> ,并且不清楚在这种情况下会发生什么;其次,因为已经有一个内置的语言功能 ( coercion ) 可以将 Vec<T> 转换为或 &[T; n]进入&[T] ,而您没有利用它。

我想写一个 new看起来基本上像这样的功能:

    fn new<T>(name: &'a str, data: &'a [T]) -> Self
where
// what goes here?

这将自动与 &[T; n] 一起使用, &Vec<T> , &Cow<T>等等,如果我们可以告诉编译器如何处理 T .您可以创建一个知道如何转换 &'a [Self] 的特征是有道理的至 Data并为 i32 实现和 f64 ,所以让我们这样做:

trait Item: Sized {
fn into_data<'a>(v: &'a [Self]) -> Data<'a>;
}

impl Item for i32 {
fn into_data<'a>(v: &'a [i32]) -> Data<'a> {
Data::I32(v)
}
}

impl Item for f64 {
fn into_data<'a>(v: &'a [f64]) -> Data<'a> {
Data::F64(v)
}
}

new 上的特征绑定(bind)变得微不足道:

impl<'a> DataVar<'a> {
fn new<T>(name: &'a str, data: &'a [T]) -> Self
where
T: Item,
{
Self {
name,
data: T::into_data(data),
}
}
}

我发现这比带有 From 的版本更具可读性和 AsRef , 但如果你仍然想要 From ,您可以使用通用 impl 轻松添加它:

impl<'a, T> From<&'a [T]> for Data<'a>
where
T: Item,
{
fn from(v: &'a [T]) -> Self {
T::into_data(v)
}
}

关于rust - 如何修改我的构造函数以接受切片或对数组或向量的引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54622029/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com