这个问题的重复似乎并没有为我解决问题。以下代码给出了错误:
use std::collections::HashMap;
use std::thread;
pub trait Spider : Sync + Send {
fn add_request_headers(&self, headers: &mut Vec<String>);
}
pub struct Google {}
impl Spider for Google {
fn add_request_headers(&self, headers: &mut Vec<String>) {
headers.push("Hello".to_string())
}
}
fn parallel_get(spiders: &HashMap<String, Box<Spider>>) -> std::thread::JoinHandle<()> {
let thread_spiders = spiders.clone();
thread::spawn(move || {
let headers = &mut vec![];
let spider = thread_spiders.get("Google").unwrap();
spider.add_request_headers(headers);
})
}
fn main() {
let spiders = HashMap::new();
let spider = Box::new(Google{});
spiders.insert("Google", spider);
}
在操场here上运行。
我明白了:
rustc 1.14.0 (e8a012324 2016-12-16)
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
--> <anon>:18:34
|
18 | let thread_spiders = spiders.clone();
| ^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the block at 17:87...
--> <anon>:17:88
|
17 | fn parallel_get(spiders: &HashMap<String, Box<Spider>>) -> std::thread::JoinHandle<()> {
| ^
note: ...so that types are compatible (expected &&std::collections::HashMap<std::string::String, Box<Spider>>, found &&std::collections::HashMap<std::string::String, Box<Spider + 'static>>)
--> <anon>:18:34
|
18 | let thread_spiders = spiders.clone();
| ^^^^^
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `[closure@<anon>:19:19: 23:6 thread_spiders:&std::collections::HashMap<std::string::String, Box<Spider>>]` will meet its required lifetime bounds
--> <anon>:19:5
|
19 | thread::spawn(move || {
| ^^^^^^^^^^^^^
我认为它告诉我它无法自动推断出thread_spiders
的生命周期,因为它需要'static
为线程生存足够长的时间,但它不能超过{{1}这是输入参数的生命周期。
问题是,我可以克隆'a
中的其他对象,并且它们会毫无问题地进入新线程。但由于某种原因,parallel_get
似乎绊倒了编译器。如果我是正确的,它应该具有thread_spiders
的生命周期,然后进入线程闭包。
我已尝试向'a
添加显式生命周期参数,但无法获得任何效果。如何编译此代码?
答案 0 :(得分:-1)
在这种情况下,错误消息非常混乱,但请注意这里的双符号:
(expected &&std::collections::HashMap<std::string::String, Box<Spider>>, found &&std::collections::HashMap<std::string::String, Box<Spider + 'static>>)
。
看起来它试图克隆引用。我假设你想克隆整个HashMap
。明确地将clone
称为Clone::clone(spiders)
可以提供更清晰的错误消息:
error[E0277]: the trait bound `Spider: std::clone::Clone` is not satisfied
error[E0277]: the trait bound `Spider: std::marker::Sized` is not satisfied
--> error_orig.rs:19:26
|
19 | let thread_spiders = Clone::clone(spiders);
| ^^^^^^^^^^^^ the trait `std::marker::Sized` is not implemented for `Spider`
|
= note: `Spider` does not have a constant size known at compile-time
= note: required because of the requirements on the impl of `std::clone::Clone` for `Box<Spider>`
= note: required because of the requirements on the impl of `std::clone::Clone` for `std::collections::HashMap<std::string::String, Box<Spider>>`
= note: required by `std::clone::Clone::clone`
您正在Clone::clone
上调用Box<Spider>
,这是一个拥有的特征对象。
How do I clone a HashMap containing a boxed trait object?说明可以通过向您的特征引入克隆方法来实现它,如下所示:
pub trait Spider: Sync + Send {
fn add_request_headers(&self, headers: &mut Vec<String>);
fn clone_into_box(&self) -> Box<Spider>;
}
impl Clone for Box<Spider> {
fn clone(&self) -> Self {
self.clone_into_box()
}
}
#[derive(Clone)]
pub struct Google {}
impl Spider for Google {
fn add_request_headers(&self, headers: &mut Vec<String>) {
headers.push("Hello".to_string())
}
fn clone_into_box(&self) -> Box<Spider> {
Box::new(self.clone())
}
}
How to clone a struct storing a trait object?建议为这种多态克隆方法创建一个单独的特征。