2015-01-26 7 views
9

Wie kleben Sie Funktionen (oder Funktionszeiger) zu Testzwecken in ein Array?Wie kann ich Funktionszeiger in einem Array speichern?

fn foo() -> isize { 1 } 
fn bar() -> isize { 2 } 

fn main() { 
    let functions = vec![foo, bar]; 
    println!("foo() = {}, bar() = {}", functions[0](), functions[1]()); 
} 

Dieser Code in diesem ist der Fehlercode ich Rust playground

:

error: mismatched types: 
expected `fn() -> isize {foo}`, 
    found `fn() -> isize {bar}` 
(expected fn item, 
    found a different fn item) [E0308] 

    let functions = vec![foo, bar]; 
           ^~~ 

Rust behandelt meine Funktionen (Werte) als verschiedene Typen trotz der gleichen Signaturen aufweisen, die ich überraschend finden.

+0

Ja, das ist ein Duplikat ist. –

+0

Wenn es sich um ein Duplikat handelt, geben Sie an, um was für ein Duplikat es sich handelt, damit wir es schaffen können! Diese Frage hat mir sehr geholfen, im Gegensatz zu anderen (ähnlichen) Fragen mit falschen oder wenig hilfreich akzeptierten Antworten. –

Antwort

10

Irgendwann wurde jeder Funktion aus Gründen, die ich nicht mehr kenne, ein eigener, eindeutiger Typ gegeben. Daraus ergibt sich, dass Sie den Compiler einen Hinweis geben müssen (beachten Sie den Typ auf functions):

fn foo() -> isize { 
    1 
} 
fn bar() -> isize { 
    2 
} 
fn main() { 
    let functions: Vec<fn() -> isize> = vec![foo, bar]; 
    println!("foo() = {}, bar() = {}", functions[0](), functions[1]()); 
} 

Sie können dies auch tun, wie so:

let functions = vec![foo as fn() -> isize, bar]; 
+0

Danke! Es ist immer eine Schande, wenn ein Anwendungsfall schwieriger wird. Ich hoffe, sie hatten einen Grund für diese bahnbrechende Veränderung. Den Typ auf der linken Seite zu notieren ist nicht so schlecht ~ wenn Sie wissen, wie man Signaturen von Funktionstypen schreibt, was ich noch nicht getan habe. –

+0

"fn items" haben einen Vorteil: Es vermeidet einen Aufruf durch einen Funktionszeiger, der ein virtueller Anruf ist. LLVM kann diesen Aufruf in einem Optimierungspass * devirtualisieren *, aber Fn-Item- und Unboxed-Closure-Aufrufe sollten immer direkt sein, ohne sich auf den Optimierer zu verlassen, um es richtig zu machen. – bluss

+0

Sie können sie in einem Array platzieren, aber Sie müssen ein bisschen mehr Casting haben: 'let functions = [foo als fn() -> isize, bar als fn() -> isize];' oder sogar 'let functions: [fn() -> isize; 2] = [foo, bar]; '. Du könntest auch einen Slice 'let functions machen: & [fn() -> isize] = & [foo, bar];'. – Shepmaster

Verwandte Themen