2015-01-26 22 views
9

Come si inseriscono le funzioni (oi puntatori di funzione) in un array a scopo di test?Come posso memorizzare i puntatori di funzione in un array?

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

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

Questo codice nel Rust playground

Questo è il codice di errore ottengo:

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 è trattare le mie funzioni (valori) come tipi diversi, pur avendo le stesse firme, che ho trovare sorprendente.

+0

Sì, questo è un duplicato. –

+0

Se è un duplicato, indica di che si tratta di un duplicato, quindi possiamo gestirlo! Questa domanda mi ha aiutato molto, al contrario di altre (simili) domande con risposte accettate sbagliate o inutili. –

risposta

10

Ad un certo punto di recente, a ciascuna funzione è stato assegnato un proprio tipo distinto per ... motivi che non ricordo. Risultato è che è necessario dare il compilatore un suggerimento (notare il tipo on 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]()); 
} 

Si può anche fare questo in questo modo:

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

Grazie! È sempre un peccato vedere che un caso d'uso diventa più difficile; Spero che abbiano avuto qualche motivo per questo cambio di rottura. Annotare il tipo sul lato sinistro non è così male ~ se sai come scrivere firme di tipo funzione, cosa che non ho ancora fatto. –

+0

"Gli oggetti fn" hanno un vantaggio: evita una chiamata attraverso un puntatore a funzione che è una chiamata virtuale. LLVM può * devirtualize * che chiama un passaggio di ottimizzazione, ma le chiamate di chiusura fn e unboxed devono sempre essere dirette, senza fare affidamento sull'ottimizzatore per farlo correttamente. – bluss

+0

Puoi metterli in un array, ma devi fare un po 'più di casting: 'let functions = [foo as fn() -> isize, bar as fn() -> isize];' o anche 'let function: [fn() -> isize; 2] = [pippo, bar]; '. Puoi anche fare una sezione 'lascia le funzioni: & [fn() -> isize] = & [foo, bar];'. – Shepmaster

Problemi correlati