隐藏和接收通用 T 对象

Hiding and receiving generic T objects

给出以下 Rust 代码:

struct Wrapper<T> {
    data: Vec<T>, // more attributes...
}

trait DataWrapper<T> {
    fn get_column(&self) -> &Vec<T>;
    fn get_data(&self, row: usize) -> &T;
}

impl<T> DataWrapper<T> for Wrapper<T> {
    fn get_column(&self) -> &Vec<T> {
        &self.data
    }

    fn get_data(&self, row: usize) -> &T {
        &self.data[row]
    }
}

struct Inter<T> {
    inter_value: Wrapper<T>,
}

trait GetInter {
    fn get_count(&self) -> &str;
}

impl GetInter for Inter<i32> {
    fn get_count(&self) -> &str {
        "i32"
    }
}

impl GetInter for Inter<f64> {
    fn get_count(&self) -> &str {
        "f64"
    }
}

fn create_vector() -> Vec<Box<GetInter>> {
    // Add some sample data
    let x = Wrapper { data: vec![1, 2, 3] };
    let y = Wrapper { data: vec![1.1, 2.2, 3.3] };

    let mut vec: Vec<Box<GetInter>> = Vec::new();

    let m = Inter { inter_value: x };
    let m = Box::new(m);
    let m = m as Box<GetInter>;
    vec.push(m);

    let n = Inter { inter_value: y };
    let n = Box::new(n);
    let n = n as Box<GetInter>;
    vec.push(n);

    vec
}

struct ColumnWrapper {
    columns: Vec<Box<GetInter>>, // more attributes
}

fn create_column_wrapper() -> ColumnWrapper {
    let result = create_vector();

    ColumnWrapper { columns: result }
}

fn main() {
    let result = create_column_wrapper();

    for iter1 in result.columns {
        println!("1: {}", iter1.get_count());
    }
}

Wrapper<T> 存储一个通用的 Vec,详细地存储列存储中的一个数据列。相应的实现returns Vec 或具体元素作为参考。

Inter<T>GetInter 特征的想法是隐藏通用 T 对象,它来自 Wrapper 的 Vec<T> 通用数据类型。 get_count() 方法仅用于测试目的。

create_vector() 使用一些示例数据创建两个新的 Vec。结果被转换为 GetInter,包装成 Box 并存储在 Vec<Box<GetInter>> 中。最后,调用者将创建一个新的 ColumnWrapper 元素。现在给出了通用数据表示。

编译后运行给出正确的结果:

i32 
f64

现在真正的问题开始了。我尝试访问存储在 Wrapper<T> 中的原始数据。

我的第一个想法是使用 Rust 的动态调度功能。它应该在运行时检测真实的数据类型。

main()函数修改:

fn main() { 
    let result = create_column_wrapper();

    for iter1 in result.columns {
        println!("1: {}", iter1.get_count());

        for iter2 in dyn_dispatch(*iter1) {
            println!("2: {}", iter2);
        }
    }
}

对应的未测试dyn_dispatch()函数:

trait Foo<T> {
    fn method(x: &Inter<T>) -> &Vec<T>;
}

impl<i32> Foo<i32> for Inter<i32> {
    fn method(x: &Inter<i32>) -> &Vec<i32> {
        &x.inter_value.data
    }
}

impl<f64> Foo<f64> for Inter<f64> {
    fn method(x: &Inter<f64>) -> &Vec<f64> {
        &x.inter_value.data
    }
}

fn dyn_dispatch<T>(x: &GetInter) -> &Vec<T> {
    Foo::method(&x as &Inter<T>)
}

编译失败并抛出错误:

85:2 error: conflicting implementations of trait Foo<_> for type Inter<_>: [E0119]

知道如何修复编译错误或其他错误以及 更多 隐藏和访问通用 T 对象的简单想法吗?

这里有几个问题。

第一个错误:

error: conflicting implementations of trait Foo<> for type Inter<>: [E0119]

其实指的是这些:

impl<i32> Foo<i32> for Inter<i32> { ... }
impl<f64> Foo<f64> for Inter<f64> { ... }

因为 i32f64 是参数,它们都等同于:

impl<T> Foo<T> for Inter<T> { ... }

也就是说,Foo<T> 对于 Inter<T> 对于任何 T 的实现因此是相互冲突的实现。解决方法是将它们写成:

impl Foo<i32> for Inter<i32> { ... }

下一个问题是您实际上并没有进行动态调度。您的 dyn_dispatch 函数必须在编译时指定或推断出 T;它不能每次 return 不同的类型;同样,您不能像那样从 GetInter 向下转换为 Inter<T>。您需要按照与 GetInter::get_count.

相同的方式进行操作