2017-05-11 2 views
1

Ich möchte mitteilen, dass" diese Methode zurückgegeben wird Struct, die Trait und Sized implementiert ". Einfache Auflösung ist nur Struct in Box gesetzt, aber ich kann nicht, weil Struct hat so große generische Parameter, die ich nicht manuell schreiben kann.Wie kann ich `Sized` für Boxed Wert angeben

// 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()); 
} 

kann ich func Funktion bearbeiten, aber ich kann nicht andere.

Wie kann ich angeben, dass Trait Sized implementiert? Ist es so etwas wie unten?

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

Antwort

1

Angesichts der Spezifikation die einzige Möglichkeit, die Sie umgehen können, ist 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

Warum andere Ansätze werden Ihre Probleme nicht lösen:

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

  1. Monomorphisized Charakterzug 0 Sie möchten func an need_size übergeben. Genauer gesagt möchten Sie Box an die need_size-Funktion übergeben.

    1. Ändern Funktion Signatur Box<Struct>

    Fehler [E0277]: das Merkmal std::boxed::Box<Struct>: Trait gebunden ist nicht zufrieden

    --> <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` 
    

    Dieses won‘ t arbeiten, weil Sie entweder Box oder Struct nicht kontrollieren können, da sie nicht in Ihrer Kiste definiert sind, und es würde mit Kohärenz r durcheinander bringen Ules. In Zukunft könnte dies mit speziellen Kohärenzregeln gelöst werden.

+0

Danke für Ihre Hilfe! –

+0

Ein [type alias] (https://doc.rust-lang.org/book/type-aliases.html) funktioniert möglicherweise auch mit weniger Ausführlichkeit (und l Flexibilität). – trentcl

1

Ich glaube, Sie müssen in der Lage sein, entweder func oder need_sized für diese Änderungen zu arbeiten. Wie sie sind, gibt func eine trait object zurück, die unsized ist, während need_sized einen konkreten Typ erfordert (mehr als das, erfordert es vollen Besitz seines Parameters item, nicht nur eine Referenz).

Ansatz 1: wenn Sie steuern und func() ändern können, können Sie es ändern, um eine Box<Struct> statt Box<Trait> zurückzukehren:

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 
} 

Ansatz 2: wenn Sie func() nicht aber tun Kontrolle steuern need_sized und Traithttps://stackoverflow.com/a/33687996/497364

playground

01: Sie können wie in dieser Antwort die Box zurück zu einem Struct niedergeschlagenen
+0

Danke für die nette Antwort. Aber was dieses Problem erschwert, ist, dass ich 'Struct' einfach nicht schreiben kann. Denn 'Struct' hat so große generische Parameter, dass ich einfach nicht schreiben kann. Hast du eine Idee ? –

+0

@AtsukiTakahashi Wenn das Tippen Ihre Hauptsorge ist, können Sie vielleicht einfach einen [type alias] (https://doc.rust-lang.org/book/type-aliases.html) erstellen (zB 'type Short = Long <'a, T, Box > 'oder was hast du, und dann verwenden Sie' Short 'statt der langen Version. – trentcl

1

Die Fehlermeldung lautet;

Fehler [E0277]: das Merkmal std::boxed::Box<Trait>: Trait gebunden ist nicht zufrieden

So hinzuzufügen; impl Trait for Box<Trait> {} nach Zeile drei lässt es kompilieren.

+0

Vielen Dank für Ihre Antwort. Also für den Fall, dass wir nicht 'impl Trait für Box '(z. B.' Trait' ist nicht unser Code), wie machen wir das? –

+0

Versuchen Sie eine newtype struct. – kvsari

+0

Ich denke das [hier] (https://doc.rust-lang.org/nightly/book /second-edition/ch19-03-advanced-traits.html#the-newtype-pattern-to-implement-external-traits-on-external-types) erklärt, was Sie tun müssen – kvsari

Verwandte Themen