使用需要大小的特征对象 [英] Working with trait objects requiring sized

查看:88
本文介绍了使用需要大小的特征对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要一个 LinkedList 的trait对象包装器结构体。内部将是Ssl流或非Ssl流的流类型。我的希望是传递结构包装,只要内部符合相同的特征,无论使用何种内部流类型,一切都会好的。



简单例如:

 使用std :: sync :: {Arc,Mutex}; 
使用std :: collections :: LinkedList;
使用std :: os :: unix :: io :: {RawFd,AsRawFd};

pub trait HRecv {}
pub trait HSend {}
pub trait HStream:HRecv + HSend + AsRawFd + Clone {}
pub结构Stream< T:HStream> ; {
pub inner:T
}

pub type StreamList = Arc< Mutex< LinkedList< Stream< HStream>>>>

fn main(){
let mut list = Arc :: new(Mutex :: new(LinkedList ::< Stream< HStream>> :: new()));
}

产生以下错误:

 错误:特性'core :: marker :: Sized'未针对类型'HStream'实现[E0277] 
let mut list = Arc :: new (互斥::新(链表::<流< HStream>> ::新()));
^ ~~~~~~~~~~~~~~



I'已经尝试在 HStream 的定义中添加 + Sized ,并使 inner code> a Box< T> ,都会产生相同的错误。

用Rust来做这个?如果是这样,语法是什么?

解决方案

好的,这里有一些问题。处理编译器错误列表:

 < anon>:15:53:15:68错误:特质`核心:: marker :: Sized`不针对类型`HStream`实施:
< anon>:15 let mut list = Arc :: new(Mutex :: new(LinkedList ::< Stream< HStream>> ::新()));
^ ~~~~~~~~~~~~~~
< anon>:15:53:15:68 help:查看E0277
< anon>的详细解释;:15:53:15:68注意:`HStream`在编译时没有已知的常量大小
< anon>:15:53:15:68注意:`Stream`需要

因为 HStream 没有编译时可计算大小,它不能替代类型参数 T 所有类型参数隐式地要求替换类型的编译时大小。如果你想允许动态调整大小的类型,你需要明确地选择退出这个隐式的限制,例如:

 << ; T:尺寸+ HStream> 

< anon>:15:53:15:68错误:特征`HStream`没有为`HStream`类型实现[E0277]
< anon>:15 let mut list = Arc :: new(Mutex :: new(LinkedList ::< Stream< HStream>> :: new()));
^ ~~~~~~~~~~~~~~
< anon>:15:53:15:68 help:查看E0277
< anon>的详细解释;:15:53:15:68注意:'Stream`需要

实施自己。您正在询问实现的类型 HStream ,但 HStream 未实现本身(它将如何?)



您必须提供 类型。

 < anon>:15:53:15:68错误:无法将特征'HStream'制作成对象[E0038] 
< anon>:15 let mut list = Arc :: new(Mutex :: new(LinkedList ::< Stream< HStream>> :: new()));
^ ~~~~~~~~~~~~~~
< anon>:15:53:15:68 help:查看E0038
< anon>的详细解释;:15:53:15:68注意:特征不能要求`Self:Sized`

这是KO问题: HStream 不能与动态分派 period 一起使用。这不是对象安全的。这很可能是因为克隆要求。



以上所有的修复都是重新设计您的类型使问题不存在。因为这里没有足够的背景来告诉你想要做什么,所以这是不可能知道的。



然而,在盲目的刺中,这是它可能看起来像没有泛型(你似乎没有使用它):


$ b

 使用std :: sync :: {Arc,Mutex}; 
使用std :: collections :: LinkedList;
使用std :: os :: unix :: io :: {RawFd,AsRawFd};

酒吧特质HRecv {}
酒吧特质HSend {}
酒吧特质HStream:HRecv + HSend + AsRawFd + CloneHStream {}
$ b $酒吧特色CloneHStream {fn clone_h_stream(&self) - >盒及LT; HStream取代; }

impl< T> CloneHStream for T其中T:'static + Clone + HStream {
fn clone_h_stream(& self) - >盒及LT; HStream> {
Box :: new(self.clone())
}
}

pub struct Stream {
酒吧内部:Box< HStream>
}

pub type StreamList = Arc< Mutex< LinkedList< Stream>>>

fn main(){
let mut list = Arc :: new(Mutex :: new(LinkedList ::< Stream> :: new()));
}


I'd like to have a LinkedList of trait object wrapper structs. The inner would be a stream type for either an Ssl or Non-Ssl stream. My hope was to pass the struct wrapper around, and as long as the inner conformed to the same trait, everything would be OK regardless of inner stream type being used.

Simple example:

use std::sync::{Arc, Mutex};
use std::collections::LinkedList;
use std::os::unix::io::{RawFd, AsRawFd};

pub trait HRecv {}
pub trait HSend {}
pub trait HStream: HRecv + HSend + AsRawFd + Clone {}
pub struct Stream<T: HStream> {
    pub inner: T
}

pub type StreamList = Arc<Mutex<LinkedList<Stream<HStream>>>>;

fn main() {
    let mut list = Arc::new(Mutex::new(LinkedList::<Stream<HStream>>::new()));
}

Produces the following error:

error: the trait 'core::marker::Sized' is not implemented for the type 'HStream' [E0277]
let mut list = Arc::new(Mutex::new(LinkedList::<Stream<HStream>>::new()));
                                                ^~~~~~~~~~~~~~~

I've tried adding + Sized to the definition of HStream, as well as making inner a Box<T>, both produce the same error.

Is it currently possible to do this with Rust? If so, what would the syntax be?

解决方案

Ok, there are a few problems here. Working down the list of compiler errors:

<anon>:15:53: 15:68 error: the trait `core::marker::Sized` is not implemented for the type `HStream` [E0277]
<anon>:15     let mut list = Arc::new(Mutex::new(LinkedList::<Stream<HStream>>::new()));
                                                              ^~~~~~~~~~~~~~~
<anon>:15:53: 15:68 help: see the detailed explanation for E0277
<anon>:15:53: 15:68 note: `HStream` does not have a constant size known at compile-time
<anon>:15:53: 15:68 note: required by `Stream`

Because HStream does not have a compile-time computable size, it cannot be substituted for the type parameter T. All type parameters implicitly require the substituted type to be compile-time sized. If you want to allow dynamically sized types, you need to explicitly opt-out of this implicit bound by saying something like:

<T: ?Sized + HStream>

<anon>:15:53: 15:68 error: the trait `HStream` is not implemented for the type `HStream` [E0277]
<anon>:15     let mut list = Arc::new(Mutex::new(LinkedList::<Stream<HStream>>::new()));
                                                              ^~~~~~~~~~~~~~~
<anon>:15:53: 15:68 help: see the detailed explanation for E0277
<anon>:15:53: 15:68 note: required by `Stream`

A trait doesn't implement itself. You're asking for a type which implements HStream, but HStream doesn't implement itself (how would it?)

You have to provide a type which does.

<anon>:15:53: 15:68 error: the trait `HStream` cannot be made into an object [E0038]
<anon>:15     let mut list = Arc::new(Mutex::new(LinkedList::<Stream<HStream>>::new()));
                                                              ^~~~~~~~~~~~~~~
<anon>:15:53: 15:68 help: see the detailed explanation for E0038
<anon>:15:53: 15:68 note: the trait cannot require that `Self : Sized`

And here's the K-O problem: HStream cannot be used with dynamic dispatch, period. It's not object safe. This is most likely because of the Clone requirement.

The "fix" to all of the above is to redesign your types so that the problem doesn't exist. What that entails is impossible to know because there isn't enough context here to tell what you're trying to do.

At a blind stab, though, here's what it might look like without generics (which you don't appear to be using, anyway):

use std::sync::{Arc, Mutex};
use std::collections::LinkedList;
use std::os::unix::io::{RawFd, AsRawFd};

pub trait HRecv {}
pub trait HSend {}
pub trait HStream: HRecv + HSend + AsRawFd + CloneHStream {}

pub trait CloneHStream { fn clone_h_stream(&self) -> Box<HStream>; }

impl<T> CloneHStream for T where T: 'static + Clone + HStream {
    fn clone_h_stream(&self) -> Box<HStream> {
        Box::new(self.clone())
    }
}

pub struct Stream {
    pub inner: Box<HStream>
}

pub type StreamList = Arc<Mutex<LinkedList<Stream>>>;

fn main() {
    let mut list = Arc::new(Mutex::new(LinkedList::<Stream>::new()));
}

这篇关于使用需要大小的特征对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆