2014-09-17 11 views
7

C++ è stato criticato perché manca la compilazione separata di modelli. I modelli C++ sono compilati per (praticamente) ogni istanza. Qual è lo stato delle cose per Rust riguardo alla compilazione separata dei generici? La mia comprensione è che si comporta come C++ eccetto che le istanze vengono memorizzate nella cache durante la compilazione di ciascuna cassa. È corretto ?Compilazione separata per generici in Rust

+0

Sono un po 'confuso su dove i modelli si adattano in C++, ma in Rust dove sono interessate le macro è possibile ottenere il modulo espanso con '--pretty expanded'. Ma non i generici. –

+2

In realtà, il vero problema in C++ non è che i template siano compilati per ogni istanza: i compilatori intelligenti eseguono la memoizzazione e hanno una cache di un numero di istanze "precompilate" di un modello per un determinato set di tipi/valori. Il problema principale è * compilazione separata * combinata con '# include', il modello deve essere presente nelle intestazioni, quindi viene analizzato inutilmente in ogni singola unità di traduzione indipendentemente dal fatto che lo utilizzi o meno. Questo problema scomparirà con i moduli (forse C++ 17). –

risposta

3

Per quanto ne so, i farmaci generici sono memorizzati in qualche forma serializzata nella cassa in cui sono definiti. Quando vengono utilizzati in un'altra cassa (libreria o binario) vengono istanziati da questa forma serializzata. Quindi sono monomorfizzati allo stesso modo dei modelli C++ ma viene evitato il sovraccarico di ripetuti parsing di codice non necessario.

2

Dalla documentazione del tutorial:

Il compilatore Rust compila funzioni generiche in modo molto efficiente da loro monomorphizing. La monomorfizzazione è un nome di fantasia per un'idea semplice: genera una copia separata di ogni funzione generica in ogni sito di chiamata, una copia specializzata per i tipi di argomento e può quindi essere ottimizzata specificamente per loro. A tale riguardo, i generici di Rust hanno caratteristiche di performance simili a modelli C++. http://doc.rust-lang.org/0.11.0/tutorial.html#generics

EDIT: questo non ha davvero rispondere alla tua domanda, vero?

+1

Quel testo è esattamente il motivo per cui ho congetturato che è lo stesso del C++. Mi piacerebbe sentire qualcosa di più esplicito, però. – Gepp

1

I tipi e le funzioni generici sono monomorfizzati. Tuttavia, è possibile utilizzare tratti senza generici.

Questa è una funzione generica. Sarà monomorfizzato.

fn get_length<T: Collection>(collection: &T) -> uint { 
    collection.len() 
} 

Questa è una funzione non generico equivalente. Solo una copia di questa funzione sarà inclusa nel file binario.

fn get_length(collection: &Collection) -> uint { 
    collection.len() 
} 

noti che non abbiamo potuto fare una funzione che riceve un Collection per valore, perché Collection è un tratto, e quindi non ha dimensione specifica. In questo caso è richiesta una funzione generica.

Ci sono alcune cose che non si possono fare con i generici e alcune cose che non si possono fare con i riferimenti di tratto. Con riferimenti tratti, hai bisogno di un tratto, ovviamente. Con i generici, non è possibile avere un vettore di raccolte in cui le raccolte sono di diverso tipo (ad esempio non è possibile inserire un Vec<int> e un String in quel vettore), ma è possibile utilizzare i riferimenti tratti: a e può contenere uno a &String.