如何为盒装值指定`Sized`

时间:2017-05-11 10:36:31

标签: rust

我想通知“此方法将返回实施StructTrait”的装箱Sized。 简单的解决方案只是将Struct放入Box但我不能,因为Struct具有如此大的通用参数,我无法手动编写。

// I can't edit these trait and struct.
trait Trait {}
struct Struct();
impl Trait for Struct {}

// This is my code.
fn func() -> Box<Trait> {
    Box::new(Struct{})
}

// This is not my code.
fn need_sized<T: Trait + Sized>(item: T) {
    println!("ok");
}

fn main() {
    // This can not be compiled!
    need_sized(func());
}

我可以修改func功能,但我不能编辑其他功能。

如何指定Trait实现大小? 它有点像下面的东西吗?

fn func() -> Box<Trait + Sized>

3 个答案:

答案 0 :(得分:1)

我认为您需要更改funcneed_sized才能生效。实际上,func会返回未归类的trait object,而need_sized需要具体类型(更重要的是,它需要对其参数item的完全所有权,而不仅仅是参考)。

方法1:如果您控制并可以更改func(),则可以将其更改为返回Box<Struct>而不是Box<Trait>

fn func() -> Box<Struct> {
    Box::new(Struct{})
}

fn main() {
    let s1 = func(); // Box<Struct>, needs dereferencing with *
                     // to become a Struct
    need_sized(*s1); // this now works
}

方法2:如果您不控制func()但是控制need_sizedTrait,您可以将Box向下转换回结构,如下所示:https://stackoverflow.com/a/33687996/497364

playground

use std::any::Any; // needed for downcast

trait Trait {
    fn as_any(&self) -> &Any;
}

struct Struct{}
impl Trait for Struct {
    fn as_any(&self) -> &Any {
        self
    }
}

fn func() -> Box<Trait> {
    Box::new(Struct{})
}


// changed to accept a &T
fn need_sized<T: Trait + Sized>(_item: &T) { 
    println!("ok");
}

fn main() {
    let s2 = func(); 
    if let Some(st) = s2.as_any().downcast_ref::<Struct>() {
        need_sized(st);
    }
}

答案 1 :(得分:1)

错误信息是;

  

错误[E0277]:不满足特征限制std::boxed::Box<Trait>: Trait

添加; impl Trait for Box<Trait> {} 在第三行之后让它编译。<​​/ p>

答案 2 :(得分:1)

根据规范,您可以绕过此方法的唯一方法是制作newtype wrapper

// I can't edit these trait and struct.
trait Trait {}
struct Struct();
impl Trait for Struct {}


// This is my code.
struct MyStruct(Struct);
impl Trait for Box<MyStruct> { /* if there is code here delegate to inner `Struct` */}

fn func() -> Box<MyStruct> {
    Box::new(MyStruct(Struct{}))
}

// This is not my code.
fn need_sized<T: Trait + Sized>(item: T) {
    println!("ok");
}

fn main() {
    // This can not be compiled!
    need_sized(func());
}

playground

为什么其他方法无法解决您的问题:

  1. 单变性特征

    fn func<T: Trait>() -> Box<T> { ... }

  2. 您想将func传递给need_size。更具体地说,您希望将Box传递给need_size函数。

    1. 将功能签名更改为Box<Struct>
    2.   

      错误[E0277]:不满足特征限制std::boxed::Box<Struct>: Trait

      --> <anon>:22:5
        |
      22|     need_sized(func());
        |     ^^^^^^^^^^ the trait `Trait` is not implemented for   `std::boxed::Box<Struct>`
        |= help: the following implementations were found:
               <std::boxed::Box<MyStruct> as Trait>
         = note: required by `need_sized`
      

      这不起作用,因为您无法控制BoxStruct,因为它们未在您的箱子中定义,并且会搞乱一致性规则。将来,这可以使用特殊的一致性规则来解决。