我正试图通过一个频道发送Vec<Box<Trait>>。我想,发送部分起作用了。在对recv()进行Vec之后,我尝试对其进行迭代,并将内部值的引用传递给一个函数,如果出现错误,该函数将失败:
error[E0277]: the trait bound `&std::boxed::Box<AwesomeTrait + std::marker::Send>: AwesomeTrait` is not satisfied
--> src/main.rs:12:13
|
12 | K::abc(&something);
| ^^^^^^ the trait `AwesomeTrait` is not implemented for `&std::boxed::Box<AwesomeTrait + std::marker::Send>`
|
note: required by `K::abc`
--> src/main.rs:57:5
|
57 | pub fn abc<T: AwesomeTrait>(something: &T) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^有没有办法从Box中获取内在价值?
这是一个最小的复制。
use std::sync::mpsc;
use std::thread;
fn main() {
let (tx, rx) = mpsc::channel::<Request>();
let s = Something::new();
tx.send(Request::Do(s)).unwrap();
let z = thread::spawn(move || match rx.recv().unwrap() {
Request::Do(somethings) => for something in somethings.list.iter() {
K::abc(&something);
},
});
z.join();
}
pub enum Request {
Do(Something),
}
pub struct Something {
list: Vec<Box<AwesomeTrait + Send>>,
}
impl Something {
pub fn new() -> Self {
Self { list: Vec::new() }
}
pub fn from<T: AwesomeTrait + Send + 'static>(something: T) -> Self {
let mut list = Vec::with_capacity(1);
list.push(Box::new(something));
// Self { list }
Self { list: Vec::new() }
}
pub fn push<T: AwesomeTrait + Send + 'static>(&mut self, something: T) {
self.list.push(Box::new(something));
}
}
pub trait AwesomeTrait {
fn func(&self);
}
pub struct X {}
impl AwesomeTrait for X {
fn func(&self) {}
}
pub struct K {}
impl K {
pub fn abc<T: AwesomeTrait>(something: &T) {
&something.func();
}
}发布于 2018-06-12 21:11:24
请允许我就这一表述的类型发表评论:
for s in somethings.list.iter() {
K::abc(&s);
}(为了避免混淆,我重新命名了迭代器变量)。
something的类型是:Something。something.list的类型是:Vec<Box<AwesomeTrait + Send>>。somethings.list.iter()是std::slice::Iter<...>类型(不重要)。s是&Box<AwesomeTrait + Send>型的。需要注意的是,它是对一个框的引用,因为您使用的是iter()而不是into_iter()。要获得实际的AwesomeTrait,您需要取消引用s以获得Box,然后再取消引用以获得内部对象:**s。
但是**s是AwesomeTrait类型的,您需要对它进行引用,所以必须使用&**s获取地址,这是&AwesomeTrait类型的地址。
由此产生的代码如下:
for s in somethings.list.iter() {
K::abc(&**s);
}或者如果您愿意使用列表:
for s in somethings.list.into_iter() {
K::abc(&*s);
}如果您不想考虑使用多少*,可以使用由Box实现的AsRef特性,并信任编译器的自动引用:
for s in somethings.list.iter() {
K::abc(s.as_ref());
}注意:.into_iter()也可以滑动。与.iter()一样,如果您迭代对Vec的引用
for s in somethings.list { //consume the list
K::abc(&*s);
}或者:
for s in &somethings.list { //do not consume the list
K::abc(&**s);
}你以为你已经完成了但还没有..。此代码引发此编译器错误:
error[E0277]: the trait bound `AwesomeTrait + std::marker::Send: std::marker::Sized` is not satisfied
--> src/main.rs:12:13
|
12 | K::abc(&**s);
| ^^^^^^ `AwesomeTrait + std::marker::Send` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `AwesomeTrait + std::marker::Send`
note: required by `K::abc`
--> src/main.rs:57:5
|
57 | pub fn abc<T: AwesomeTrait>(something: &T) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^为什么会这样呢?好吧,您的K::abc需要对实现AwesomeTrait和&AwesomeTrait的类型的引用。但是,一个特征是非大小类型(DST),所有泛型函数类型参数默认都需要Sized类型。
解决方案是将?Sized不需要添加到K::abc中。
impl K {
pub fn abc<T: AwesomeTrait + ?Sized>(something: &T) {
something.func();
}
}(这个函数中有一个&,它什么也不做,我已经删除了它)。
该?Sized的限制是您不能声明T类型的变量或参数,只能声明&T、&mut T、Box<T>.但是你现在的代码没有什么禁止的,所以没问题。
发布于 2018-06-12 20:54:04
您很可能希望取消引用Box<Trait>,以便返回一个Trait,但这显然是一个不大小的类型,因此您将立即需要引用它,如下所示:
K::abc(&*something)但是,等等!iter()不使用Vec<Box<Trait>>的所有权,因此每个元素都是&Box<Trait>类型的。要解决这个问题,我们需要调用into_iter():
for something in somethings.list.into_iter() {
K::abc(&*something);
}https://stackoverflow.com/questions/50824801
复制相似问题