我終於決定給Rust(1.7 & 1.8)一試。來自C++,我必須說Rust看起來很棒。我試圖在C++中重現一個衆所周知的行爲,其中包括在一組對象上使用動態多態。在指定自我生命期時使用特質上的動態多態性使用Rust的問題
我經歷了一個非常煩人的問題,我能解決,但我想知道你們對這個問題的看法,我希望它可以幫助其他人試圖做同樣的事情。
讓我們看看下面的代碼實現了最初的想法:
struct Foo
{
foo: u32,
}
trait Bar
{
fn bar(& self) -> u32;
}
impl Bar for Foo
{
fn bar(& self) -> u32
{
return self.foo;
}
}
fn foobar(l: &std::collections::LinkedList<& Bar>)
{
for i in l
{
println!("{}", i.bar());
}
}
fn main()
{
let foo0 = Foo{foo: 8u32};
let foo1 = Foo{foo: 8u32};
let mut l = std::collections::LinkedList::new();
l . push_back(&foo0 as &Bar);
l . push_back(&foo1 as &Bar);
foobar(&l);
}
這裏的一切編譯,一切都可以正常使用。
我想通過另一個參考功能bar
的性狀Bar
,因此我不得不增加一生的Bar
性狀。爲了簡單起見,我將添加生命週期(因爲它將在Rust 1.8下很好地編譯)。通過整個代碼添加使用壽命後,代碼最終看起來像這樣:
struct Foo
{
foo: u32,
}
trait Bar<'a>
{
fn bar(& 'a self) -> u32;
}
impl<'a> Bar<'a> for Foo
{
fn bar(& 'a self) -> u32
{
return self.foo;
}
}
fn foobar<'a>(l: &std::collections::LinkedList<& 'a Bar>)
{
for i in l
{
println!("{}", i.bar());
}
}
fn main()
{
let foo0 = Foo{foo: 8u32};
let foo1 = Foo{foo: 8u32};
let mut l = std::collections::LinkedList::new();
l . push_back(&foo0 as &Bar);
l . push_back(&foo1 as &Bar);
foobar(&l);
}
如果你編譯這段代碼,錯誤信息將在以下幾點:
../test.rs:21:12: 21:13 error: cannot infer an appropriate lifetime due to conflicting requirements [E0495]
../test.rs:21 for i in l
^
../test.rs:19:1: 25:2 help: consider using an explicit lifetime parameter as shown: fn foobar<'a>(l: &std::collections::LinkedList<&'a Bar>)
../test.rs:19 fn foobar<'a>(l: &std::collections::LinkedList<& 'a Bar>)
../test.rs:20 {
../test.rs:21 for i in l
../test.rs:22 {
../test.rs:23 println!("{}", i.bar());
../test.rs:24 }
...
error: aborting due to previous error
這裏的問題是清楚的,編譯器知道push_back
中給出的變量具有不同的生命期,因此它不符合我所寫的內容。如果在相同的let
語句中聲明變量foo0
和foo1
,則可以解決問題。
我發現很難弄清楚那段代碼出了什麼問題。 我的問題是:
有沒有辦法告訴集合可能會採取不同的生命週期的編譯器?
通過在另一個引用變量(此處未顯示)上設置
'a
生命週期而不是self
,代碼將進行編譯。這是否意味着如果我們沒有指定任何生命週期,那麼編譯器將'_
與我在前一個問題中提到的具體生命週期相對應?有沒有隱含的規則,「禁止」我們設置自己的一生?
這段代碼是否慣用Rust?
http://codereview.stackexchange.com/可能更適合於這種問題... –
請讓每[只有一個問題問題](http://meta.stackexchange.com/q/39223/281829)。在Code Review中可以找到「是否習慣用語」的答案,但請在此處移動您的問題之前查看[此帖子](http://meta.codereview.stackexchange.com/q/5777/32521)。也許你可以選擇其中一個功能性問題,並將你的問題重新編寫爲專注於它的開始? – Shepmaster
@LukasKalbertodt:不,看起來並不是因爲1.)錯誤被提及,並且2.)所有'Foo'和'Bar's都表明這主要是假設代碼。 – Jamal