Je ne pense pas qu'il y ait un moyen de générer les index au moment de la compilation, sauf en utilisant une fonction enum
(ce que je considère comme une approche parfaitement raisonnable). Je ne suis pas sûr qu'un modèle puisse aider, parce que les modèles sont purement fonctionnels et qu'il n'y a aucun endroit où stocker un état global (c'est-à-dire l'index actuel), sauf dans le nom du type modélisé lui-même (ce qui est exactement ce que vous essayez d'éviter).
Si vous voulez vraiment des ID entiers, il est probablement plus facile de les configurer au moment de l'exécution plutôt que d'essayer trop fort.
Tout d'abord, il faut avoir un objet qui représente un type, et utiliser l'approche artisanale typique de la RTTI : chaque classe doit avoir une instance statique de cet objet, et sa fonction virtuelle get-type-info doit retourner un pointeur vers cet objet. Ainsi, chaque classe aurait un petit bout de code, comme ceci :
static TypeInfo ms_type_info;
virtual const TypeInfo *GetTypeInfo() const {
return &ms_type_info;
}
Et vous définissez l'info type, en mettant dans le fichier <<whatever you info you want>>
quelle que soit l'information que le TypeInfo
pour le rendre meilleur que le RTTI du compilateur ;
TypeInfo WhateverClass::ms_type_info(<<whatever info you want>>);
(Toutes les implémentations que j'ai vues utilisent une macro pour automatiser la création de ces deux morceaux de texte ; c'est un peu laid, mais vos options sont limitées, et c'est mieux que de les taper).
Le site TypeInfo
La structure elle-même ressemblerait un peu à ceci :
struct TypeInfo {
int type_index;
TypeInfo *next;
TypeInfo(<<whatever>>) {<<see below>>}
};
Si le lecteur préfère les fonctions get et set, il peut les avoir.
Le site TypeInfo
devrait être statique à la classe, et non à la fonction, car l'intention est de créer une liste de tous les objets TypeInfos
. Vous avez deux options ici. L'option automatique est d'avoir chaque TypeInfo
L'autre consiste à avoir une grande fonction qui ajoute manuellement ceux qu'elle veut à la liste globale.
Puis, au démarrage, exécutez les TypeInfo
et leur attribuer un indice. Quelque chose comme ça pourrait faire l'affaire, en supposant qu'il y ait une TypeInfo *g_first_type_info
qui pointe vers la première info type de la liste :
int next_type_index=0;
for(TypeInfo *ti=g_first_type_info;ti;ti=ti->next)
ti->type_index=next_type_index++;
Maintenant, quand vous voulez votre ID d'entier, vous pouvez le retrouver facilement :
object->GetTypeInfo()->type_index;
Vous pourriez mettre en œuvre t
assez facilement maintenant :
virtual int t() const {
return ms_type_info.type_index;
}
Divulgation complète des problèmes auxquels je peux penser :
-
Les index de type ne sont pas définis à la compilation, donc si vous construisez des tableaux, vous devrez le faire à l'exécution. Cela peut être un gaspillage de code si vos tableaux seraient autrement des constantes au moment de la compilation - cependant pour les compilateurs qui ne supportent pas la syntaxe d'initialisation des tableaux de style C99, cela peut parfois rendre le code plus lisible.
-
Si vous aimez tout faire dans les constructeurs globaux avant que main
commence, vous risquez de ne pas vous en sortir, car les TypeInfo
ne sont que des objets globaux ordinaires et (dans cette situation de toute façon) ne sont pas vraiment prêts à être utilisés tant que les index de type n'ont pas été attribués.
-
Les éditeurs de liens ont tendance à supprimer les objets globaux qui ne semblent pas être utilisés, de sorte que les objets d'information sur les types dans les bibliothèques statiques peuvent ne jamais s'ajouter à la liste. Vous devez donc garder à l'esprit que si l'approche de l'enregistrement automatique fonctionne bien, quand elle ne fonctionne pas, elle ne fonctionne pas, et que vous pouvez finir par devoir enregistrer les choses manuellement.