2

给出以下 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存储来自列存储的通用的、详细的数据列。相应的实现返回Vec或特定元素作为参考。

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

create_vector()Vec使用一些样本数据创建两个新的 s。结果被转换为GetInter,包装成 aBox并存储在 a 中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 错误:Foo<_>类型的特征实现冲突Inter<_>:[E0119]

知道如何修复编译错误或隐藏和访问通用对象的另一个更简单的想法吗?T

4

1 回答 1

4

这里有几个问题。

第一个错误:

错误: Inter<> 类型的特征 Foo<> 的实现冲突:[E0119]

实际上是指这些:

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

由于i32f64是参数,它们都等价于:

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

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

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

下一个问题是您实际上并没有进行动态调度。您的dyn_dispatch函数必须T在编译时指定或推断;它不能每次都返回不同的类型;同样,您不能只是沮丧GetInterInter<T>喜欢那样。您需要以与您所做的相同的方式进行操作GetInter::get_count

于 2016-07-22T13:25:45.893 回答