C ++ a été critiqué car il manque de compilation de modèles séparés. Les modèles C ++ sont compilés pour (virtuellement) chaque instanciation. Quel est l'état des choses pour la rouille concernant la compilation séparée des génériques? Je crois comprendre que cela se comporte comme C ++, sauf que les instanciations sont mises en cache lors de la compilation de chaque caisse. Est-ce correct? P>
3 Réponses :
du Tutoriel Docs: P>
Le compilateur de rouille compile des fonctions génériques de manière très efficace en les monomorphisant. La monomorphisie est un nom de fantaisie pour une idée simple: générer une copie séparée de chaque fonction générique sur chaque site d'appel, une copie spécialisée dans les types d'arguments et peut ainsi être optimisée spécifiquement pour eux. À cet égard, les génériques de Rust ont des caractéristiques de performance similaires aux modèles C ++. http://doc.rust-lang.org/0.11.0/TUCTAL .html # génériques p> blockQuote>
edit: strong> Cela n'a pas vraiment répondu à votre question, n'est-ce pas? p>
Ce texte est exactement pourquoi j'ai conjecté que c'est la même chose qu'en C ++. Je voudrais entendre quelque chose de plus explicite, cependant.
Les "caractéristiques de performance similaires" désignent ici les performances d'exécution, ce qui signifie que la compilation est effectuée séparément pour chaque copie et donc aucune surcharge d'exécution. Cette phrase ne fait pas référence exactement à l'heure de la compilation.
Les types génériques et les fonctions sont monomorphisés. Cependant, il est possible d'utiliser des traits sans génériques.
Ceci est une fonction générique. Il sera monomorphe. P> Il s'agit d'une fonction non générique équivalente. Une seule copie de cette fonction sera incluse dans le binaire. P> Notez que nous ne pouvions pas faire une fonction qui reçoit une collection code> code> par valeur , parce que Il y a des choses que vous ne pouvez pas faire avec des génériques et certaines choses que vous ne pouvez pas faire avec des références de trait. Avec des références de trait, vous avez besoin d'un trait, évidemment. Avec des génériques, vous ne pouvez pas avoir de vecteur de collections où les collections sont de types différents (par exemple, vous ne pouviez pas imposer de collection code> est un trait, et il n'a donc pas de taille spécifique. Une fonction générique est requise dans ce cas. P>
VEC
VEC <& Collection> code> peut contenir un
& VEC
et de la chaîne p > p>
Autant que je sache, les génériques sont stockés sous une forme sérialisée dans la caisse où ils sont définis. Lorsqu'il est utilisé dans une autre caisse (bibliothèque ou binaire), ils sont instanciés de cette forme sérialisée. Ils sont donc monomorphisés de la même manière que les modèles C ++, mais les frais généraux de l'analyse répétée du code inutile sont évités. P>
Je suis un peu floue sur l'endroit où les modèles s'intègrent en C ++, mais dans la rouille où les macros sont préoccupées, vous pouvez obtenir la forme expansée avec
- assez développé code>. Mais pas des génériques.
En réalité, le problème réel en C ++ n'est pas que les modèles sont compilés pour chaque instanciation: les compilateurs intelligents effectuent une mémoire de mémoisation et disposent d'un cache d'un certain nombre d'instanciations "pré-compilées" d'un modèle pour quelques types de types / valeurs donnés. Le problème principal est compilation séparé i> combiné avec
#include code>, le modèle doit être dans les en-têtes, il est donc inutilement analysé dans chaque unité de traduction, que cela l'utilise ou non. Ce problème disparaîtra avec des modules (C ++ 17 peut-être?).