如何在Rust中使用未定义的类型/特征?

时间:2016-08-25 20:19:26

标签: rust

我有以下

trait T {}
type Iter = fn() -> Iterator<Item = T>;

fn func(iter: Iter) {
    for a in iter() {
        // ...
    }
}

我希望iter返回带有移动语义的迭代器,因此我不必返回&Iterator。问题是,Iterator是一个特征,所以它没有被确定。上面的代码得到一个编译错误,说Iterable不满足Sized特征,因为所有局部变量都必须是静态大小。

除此之外,T也是一种特质,因此未经过调整,因此我无法将a绑定到它,因为它未经过调整。

我是Rust的新手,所以这真的让我感到沮丧。如何使用未分类的类型?

2 个答案:

答案 0 :(得分:4)

你可能根本就不应该使用未经过类型化的类型。请改用泛型:

trait Foo {} // T is a common name for type parameters, so use a different name

fn func<I, F>(iter: F) where I: Iterator, I::Item: Foo, F: FnOnce() -> I {
  for a in iter() {
    // ...
  }
}

查看genericsFn* traits上的书籍章节。

顺便说一下,接受一个函数看起来并不是很有用,因为你只需在开始时调用它一次。编写这样的函数似乎更简单:

fn func<I>(iter: I) where I: Iterator, I::Item: Foo {
  for a in iter {
    // ...
  }
}

答案 1 :(得分:1)

仅限不合格类型&#34;工作&#34;如果涉及额外的间接水平。例如:

trait Ttait {}
fn foo(x: Trait) {}      // error: x would be unsized which is not allowed
fn bar(x: &Trait) {}     // OK: x is just a reference
fn baz(x: Box<Trait>) {} // OK: x is just an "owning pointer"

但是,您不应该使用特征作为类型,而应该更喜欢将特征用作 bounds 的特征,用于泛型函数和结构的参数

fn generic<Type: Trait>(x: Type) {}

这实际上不是一个功能,而是一个系列的功能。对于实现Type的每个类型Trait,编译器将根据需要创建generic的特殊版本。如果您具有实现x并编写Trait的具体类型的值generic(x),那么您将调用一个特别为该类型未创建的函数创建的函数。这被称为&#34;单态化&#34;。

因此,特质有两种用途。它们充当未规划类型(对于特征对象,动态分派,动态多态)以及通用代码的类型边界(静态分派,静态多态)。我的建议是尽可能避免使用特征对象,而不是通用代码。

如果不确切知道自己要做什么,请告诉我一个可能性:

trait Trait {
    fn foo(&self);
}

fn func<'x,I>(iterable: I) where I: IntoIterator<Item = &'x Trait> {
    for a in iterable {
        a.foo();
    }
}

struct Example;

impl Trait for Example {
    fn foo(&self) {
        println!("Example::foo()");
    }
}

fn main() {
    let arr = [Example, Example];
    func(arr.iter().map(|x| x as &Trait));
}

这是一个演示两种特质用途的例子。 func在它所采用的迭代类型上是通用的,但使用动态调度来调用正确的foo函数。这可能与你想要做的最接近。

你也可以去&#34;完全通用&#34; (避免动态调度foo来电。请参阅delnan的回答)或&#34;完全动态&#34; (使func不知道它在运行时实际处理的迭代器类型)。有了更多的背景,我们可能会提出更好的建议。

相关问题