2014-09-17 4 views
7

C++ wurde kritisiert, da es keine separate Zusammenstellung von Vorlagen gibt. C++ - Vorlagen werden für (virtuell) jede Instanziierung kompiliert. Wie ist der Stand der Dinge für Rust bezüglich der getrennten Zusammenstellung von Generika? Mein Verständnis ist, dass es sich wie C++ verhält, außer dass Instanziierungen während der Zusammenstellung jeder Kiste zwischengespeichert werden. Ist das korrekt ?Separate Kompilation für Generika in Rust

+0

Ich bin ein wenig verschwommen auf, wo Vorlagen in C++ passen, aber in Rust, wo Makros betroffen sind, können Sie das erweiterte Formular mit '--pretty expanded' erhalten. Aber keine Generika. –

+2

Eigentlich ist das eigentliche Problem in C++ nicht, dass Templates für jede Instanziierung kompiliert werden: Clevere Compiler führen Memoization durch und haben einen Cache mit einer Anzahl von "vorkompilierten" Instanziierungen einer Vorlage für einige gegebene Typen/Werte. Das Hauptproblem ist * separate Kompilierung * kombiniert mit '# include', die Vorlage muss in Kopfzeilen sein, so wird unnötigerweise in jeder einzelnen Übersetzungseinheit geparst, ob sie verwendet wird oder nicht. Dieses Problem wird mit Modulen verschwinden (C++ 17 vielleicht?). –

Antwort

3

Soweit ich weiß, werden Generika in irgendeiner serialisierten Form in der Kiste gespeichert, in der sie definiert sind. Wenn sie in einer anderen Kiste (Bibliothek oder Binärdatei) verwendet werden, werden sie aus dieser serialisierten Form instanziiert. So werden sie auf die gleiche Weise monomorphisiert wie C++ - Templates, aber der Aufwand beim wiederholten Parsen von unnötigem Code wird vermieden.

2

aus dem Tutorial-Dokumentation:

Der Rust-Compiler kompiliert generische Funktionen sehr effizient, indem sie monomorphizing. Die Monomorphisierung ist ein fantastischer Name für eine einfache Idee: Generiere eine separate Kopie jeder generischen Funktion an jeder Aufrufstelle, eine Kopie, die auf die Argumenttypen spezialisiert ist und somit speziell für sie optimiert werden kann. In dieser Hinsicht haben Ruts Generika ähnliche Leistungsmerkmale wie C++ - Templates. http://doc.rust-lang.org/0.11.0/tutorial.html#generics

EDIT: dies Ihre Frage nicht wirklich beantworten, es getan hat?

+1

Dieser Text ist genau, warum ich vermutete, dass es das gleiche wie in C++ ist. Ich möchte jedoch etwas expliziteres hören. – Gepp

1

Generische Typen und Funktionen sind monomorphisiert. Es ist jedoch möglich, Merkmale ohne Generika zu verwenden.

Dies ist eine generische Funktion. Es wird monomorphisiert werden.

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

Dies ist eine äquivalente nicht generische Funktion. Nur eine Kopie dieser Funktion wird in der Binärdatei enthalten sein.

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

Beachten Sie, dass wir nicht eine Funktion machen könnte, die einen Collection von Wert erhält, weil Collection ein Merkmal ist, und damit hat es keine spezifische Größe. Eine generische Funktion ist in diesem Fall erforderlich.

Es gibt einige Dinge, die Sie nicht mit Generika und einigen Dingen tun können, die Sie mit Merkmalsverweisen nicht tun können. Bei Merkmalsreferenzen brauchst du natürlich eine Eigenschaft. Bei Generika können Sie keinen Vektor von Sammlungen haben, in denen die Sammlungen unterschiedliche Typen haben (z. B. konnten Sie keinen Vec<int> und keinen String in diesen Vektor einfügen), aber Sie können mit Merkmalsreferenzen: a Vec<&Collection> können ein &Vec<int> und a .