
Envoyé par
JolyLoic
En C#, ça peut avoir du sens, mais en C++, je trouve que ça contraint souvent bien trop fortement les arguments templates. Pourquoi vouloir empêcher une autre classe qui possède toute l'interface requise d'être utilisée en tant que T ?
En fait, le fait qu'il y ait des contraintes sur les paramètres de type générique en C# et pas en C++ s'explique par la différence de fonctionnement entre les génériques de C# et les templates de C++... Ca semble similaire, mais en fait ça ne fonctionne pas du tout de la même manière.
En C++, le compilateur instancie le template avec les arguments de type qu'on lui fournit, et il vérifie que ça colle (par exemple si dans le template on appelle une méthode Toto, le compilo vérifie que cette méthode existe bien dans la classe passée en argument). Pas besoin de dire que l'argument du template doit hériter d'une classe donnée, s'il a les membres qui vont bien, ça passe. C'est une forme de "duck typing" en gros...
En C#, un type générique est compilé indépendamment des types qu'on pourrait lui passer en paramètre : c'est un type à part entière, pas juste un "modèle" pour créer d'autres types. Donc si on a besoin d'accéder à un membre d'un paramètre de type, il faut mettre des contraintes pour donner des informations plus spécifiques sur ce type. Par exemple ce code :
1 2 3 4 5 6 7
| static class Foo<T>
{
public static int Bar(T obj)
{
return obj.Count;
}
} |
ne compilera pas, parce que le compilateur ne peut pas vérifier que le type T a une propriété Count.
Si on rajoute une contrainte :
static class Foo<T> where T : ICollection
Le compilateur sait que T implémente ICollection, et qu'il a donc une propriété Count. Et là ça passe...
Pour répondre à la question d'origine : si le template appelle des méthodes de U qui sont déclarées dans V, ça ne compilera que si la classe U a effectivement ces méthodes. Donc si U hérite de V, ça passera. Mais il est aussi possible que ça passe sans que U hérite de V, à condition que U expose bien les membres nécessaires...
Bon, après je suis pas du tout expert en C++, donc je dis peut-être des bêtises... mais il me semble que c'est à peu près comme ça que ça se passe.
Partager