通用标题的道歉。
以下是一些示例代码:
use std::marker::PhantomData;
pub trait Foo {
fn foo(&self);
}
pub trait Bar<A: Foo> {
fn bar(&self, a: A);
}
pub struct Test<A, B>
where A: Foo,
B: Bar<A>
{
_phantom_r: PhantomData<A>,
bars: Vec<B>,
}
impl<A, B> Test<A, B>
where A: Foo,
B: Bar<A>
{
pub fn new() -> Test<A, B> {
Test {
_phantom_r: PhantomData,
bars: Vec::new(),
}
}
pub fn add_bar(&mut self, b: B) {
self.bars.push(b);
}
}
fn main() {
let t = Test::new();
}
错误是:
<anon>:32:13: 36:22 error: unable to infer enough type information about `_`; type annotations or generic parameter binding required [E0282]
<anon>:32 let t = Test::new();
我对Rust在推断特质类型方面遇到的问题感到困惑,以及我如何指定它想要的东西。也就是说,我不确定这是否正确,因为我遇到Sized
问题:
let t = Test::new() as Test<Foo,Bar<Foo>>;
错误:
<anon>:36:28: 36:46 error: the trait `core::marker::Sized` is not implemented for the type `Foo` [E0277]
<anon>:36 let t = Test::new() as Test<Foo,Bar<Foo>>;
我有两个主要问题:
Test<A,B<A>>
?答案 0 :(得分:6)
简短的回答是你没有告诉它使用什么类型。
解释你的声明:
pub trait Foo {}
“有一个特征Foo
”
pub trait Bar<A: Foo> {}
“如果你给我一个实施A
的{{1}}类型,我可以给你一个特征Foo
。”
Bar<A>
“如果您提供实施pub struct Test<A, B>
where A: Foo,
B: Bar<A> {}
的{{1}}类型,以及实施A
的{{1}},我会为您提供Foo
类型
B
“让我成为Bar<A>
”。这就是问题 - Test<A,B>
不是一个类型,它是一个模板,用于创建一个给定两种类型的类型(有一些限制)。在上面的示例中,您没有提供任何此类类型,只是缩小了类似的类型。
要实际使用let t = Test::new();
,您需要提供以下类型:
Test
答案 1 :(得分:0)
您可以将第一个错误归结为:
fn main() {
let v = Vec::new();
}
这里的问题是编译器无法确定向量将包含的具体类型。在您的情况下,您创建了一个结构(Test
),可以在不传递A
和B
的具体类型的情况下创建该结构,但基本推理是相同的。
第二个问题是相关的。 Foo
和Bar
都不是编译时已知大小的具体类型。尝试在需要固定大小的位置(由Sized
特征表示)中使用它们将失败。
当您实例化类型时,类型的大小必须,并且通过提供具体类型代替泛型类型参数来完成。
答案 2 :(得分:0)
关于已接受答案的说明 - 已接受的答案涵盖了识别特征的问题,但是该线程中有一些注释可以解释此问题的其他详细信息。为了便于阅读,我在这里总结了其中一个(因为评论有点难以理解)。
Static Dispatch (当您使用上述代码中的特征时使用)将不适用于矢量上的多个具体类型。
例如,举个例子:
trait Foo {
fn method(&self) -> String;
}
impl Foo for u8 {
fn method(&self) -> String {
format!("u8: {}", *self)
}
}
impl Foo for String {
fn method(&self) -> String {
format!("string: {}", *self)
}
}
struct Test<T: Foo> {
foos: Vec<T>,
}
impl<T:Foo> Test<T> {
pub fn do_something(&self, x: T) {
self.foos.push(x);
}
}
fn main() {
let x = 5u8;
let y = "Hello".to_string();
let t = Test {foos:Vec::new()};
t.do_something(x);
t.do_something(y);
}
这将不有效,因为虽然do_something()
可以使用静态调度,但Test::foos
无法。如果我们改为Test
改为:
struct Test {
}
impl Test {
pub fn do_something<T: Foo>(&self, x: T) {
x.method();
}
}
它会起作用。 main()
函数根本不需要更改(除了删除向量),它完全与Vector导致静态调度(显然)不工作。
在这种情况下,我相信Dynamic Dispatch会起作用 - 但我还不熟悉,只是在这里给出任何深入的答案/例子。希望这有助于未来的读者。