2015-06-05 18 views
12

Próbuję utworzyć funkcję zwracającą cechę, w tym przypadku moduł cieniujący Shader (który w poniższym przykładzie kodu to używany jako jako ShaderTrait). Jednak pojawia się następujący błąd:Funkcja powrotu z metody

błąd: cechę core::marker::Sized nie jest określony dla danego typu opal_core::shader::Shader

Ma to sens, ponieważ kompilator nie zna rozmiaru cechy, ale nigdzie nie mogę znaleźć zalecany sposób ustalenia tego. Oddanie odnośnika z & nie zadziałałoby (afaik), ponieważ referencja przeżyłaby czas życia jego twórcy. Być może muszę użyć Box<T>?

Oto przykładowy kod:

impl GraphicsContextTrait for GraphicsContext { 

    /// Creates a shader object 
    fn create_shader(&self, stage: Stage, source: &str) -> ShaderTrait { 
     let id; 

     unsafe { 
      id = self.functions.CreateShader(shader_stage_to_int(&stage)); 
     } 

     let shader = Shader { 
      id: id, 
      stage: stage, 
      context: self 
     }; 

     shader 
    } 
} 

Dzięki jeśli możesz pomóc.

Odpowiedz

10

Tak. W tej chwili musisz albo zwrócić &T lub Box<T>, i masz rację w tym przypadku, &T jest niemożliwe.

„Abstrakt rodzaje powrotne” stałaby powrocie T możliwe: https://github.com/rust-lang/rfcs/issues/518

+0

Wygląda na to, że typy Streszczenie powrotne bug został połączyła - jest właściwa składnia teraz po prostu 'impl T'? – dimo414

+1

To jeszcze nie jest stabilna rdza. Pojawi się na początku 2018. –

0

To może nie być dokładnie to, czego szukasz, ale myślę, że można użyć rodzajowych i statycznego wysyłkę (nie mam pojęcia, czy są to właściwe terminy, widziałem tylko, że ktoś z nich korzysta), aby stworzyć coś takiego.

To nie jest dokładnie "powracanie jako cecha", ale pozwala funkcjom ogólnie korzystać z cech. Składnia jest trochę niejasna, imo, więc łatwo ją przegapić.

Istnieje pokrewny post, o który pytałem tutaj, w sprawie zwrotu cechy Iterator. Robi się brzydko. https://stackoverflow.com/a/30641982/97964

na boisku: http://is.gd/ELgzen

struct MyThing { 
    name: String 
} 

trait MyTrait { 
    fn get_name(&self) -> String; 
} 

impl MyTrait for MyThing { 
    fn get_name(&self) -> String { 
     self.name.clone() 
    } 
} 

// This is where the magic happens 
fn as_trait<T: MyTrait>(t: T) -> T { 
    return t 
} 

fn main() { 
    let t = MyThing { name: "James".to_string() }; 
    let new_t = as_trait(t); 

    println!("Hello, world! {}", new_t.get_name()); 
} 
+0

, nawet jeśli nie dodasz funkcji as_trait(), możesz nadal wywoływać metodę 'get_name'. – Djvu

3

myślę, że to jest to, czego szukał. Przynajmniej dotarłem tutaj, kiedy go szukałem.

Prosty fabryka realizowane w Rust:

pub trait Command { 
    fn execute(&self) -> String; 
} 

struct AddCmd; 
struct DeleteCmd; 

impl Command for AddCmd { 
    fn execute(&self) -> String { "It add".into() } 
} 

impl Command for DeleteCmd { 
    fn execute(&self) -> String { "It delete".into() } 
} 

fn command(s: &str) -> Option<Box<Command+'static>> { 
    match s { 
     "add" => Some(Box::new(AddCmd)), 
     "delete" => Some(Box::new(DeleteCmd)), 
     _ => None 
    } 
} 

fn main() { 
    let a = command("add").unwrap(); 
    let d = command("delete").unwrap(); 
    println!("{}", a.execute()); 
    println!("{}", d.execute()); 
} 

https://gist.github.com/cristianoliveira/722204361927761ae69c150fde040059

Powiązane problemy