Vous pouvez envisager des modèles C++ être interprété, langage de programmation fonctionnelle déguisé en un système de médicaments génériques. Si cela ne vous fait pas peur, il devrait :)
Les génériques C# sont très restreints; vous pouvez paramétrer une classe sur un type ou des types, et utiliser ces types dans des méthodes. Ainsi, pour prendre un exemple de MSDN, vous pouvez faire:
public class Stack<T>
{
T[] m_Items;
public void Push(T item)
{...}
public T Pop()
{...}
}
Et maintenant, vous pouvez déclarer une Stack<int>
ou Stack<SomeObject>
et il va stocker des objets de ce type, en toute sécurité (pas de peur de mettre en SomeOtherObject
par erreur).
En interne, le runtime .NET le spécialise en variantes pour les types fondamentaux comme int, et une variante pour les types d'objet. Cela permet à la représentation pour Stack<byte>
d'être beaucoup plus petite que celle de Stack<SomeObject>
, par exemple.
les modèles C de permettre une utilisation similaire:
template<typename T>
class Stack
{
T *m_Items;
public void Push(const T &item)
{...}
public T Pop()
{...}
};
Cela ressemble au premier coup d'œil, mais il y a quelques différences importantes. Tout d'abord, au lieu d'une variante pour chaque type fondamental et un pour tous les types d'objet, il existe une variante pour chaque type qui est instancié par rapport à. Cela peut être beaucoup de types! La différence majeure suivante est (sur la plupart des compilateurs C++) il sera compilé dans chaque unité de traduction dans laquelle il est utilisé. Cela peut beaucoup ralentir la compilation.
Un autre attribut intéressant des modèles de C++ est qu'ils peuvent être appliqués à d'autres choses que des classes - et quand ils le sont, leurs arguments peuvent être automatiquement détectés. Par exemple:
template<typename T>
T min(const T &a, const T &b) {
return a > b ? b : a;
}
Le type T sera automatiquement déterminé par le contexte dans lequel la fonction est utilisée.
Ces attributs peuvent être utilisés à de bonnes fins, au détriment de votre santé mentale. Dans la mesure où un modèle C++ est recompilé pour chaque type contre lequel il est utilisé et que l'implémentation d'un modèle est toujours disponible pour le compilateur, C++ peut effectuer des inlining très agressifs sur les modèles. Ajouter à cela la détection automatique des valeurs de modèle dans les fonctions, et vous pouvez faire anonymous pseudo-functions en C++, en utilisant boost::lambda. Ainsi, une expression comme:
_1 + _2 + _3
produit un objet avec un de type sérieusement effrayant, qui a un opérateur() qui ajoute ses arguments. Il ya beaucoup d'autres coins sombres du système de gabarit C++ - c'est un outil extrêmement puissant, mais peut être pénible à penser, et parfois difficile à utiliser - en particulier quand il vous donne un message d'erreur de vingt pages. Le système C# est beaucoup plus simple - moins puissant, mais plus facile à comprendre et plus difficile à abuser.
Quelle coïncidence, c'est mon sujet de blog pour aujourd'hui. http://blogs.msdn.com/ericlippert/archive/2009/07/30/generics-are-not-templates.aspx –
cela a * eu * pour être exact en double. @Eric Lippert: Ooh, intéressant, va lui donner une lecture – jalf