L'une des raisons pour lesquelles j'ai tendance à éviter d'utiliser les unions étiquetées est que je n'aime pas l'idée de la pénalité de performance qu'entraîne l'utilisation d'une union étiquetée. switch/case
pour la balise pourrait être introduite si le nombre de balises est supérieur à 4 environ.
Je viens d'avoir l'idée qu'au lieu d'utiliser une balise, on pourrait placer un pointeur sur une fonction qui lirait la dernière valeur écrite dans le fichier union
. Par exemple :
union u{
char a;
int b;
size_t c;
};
struct fntag{
void (*readval)(union u *ptr, void *out);
union u val;
};
Ensuite, chaque fois que vous écrivez une valeur dans val
vous mettez également à jour le readval
en conséquence, de sorte qu'il pointe vers une fonction qui lit le dernier champ que vous avez écrit dans l'union. Oui, il y a un problème difficile, et c'est où renvoyer la valeur lue (parce que le même pointeur de fonction ne peut pas pointer vers des fonctions renvoyant des types différents). J'ai choisi de renvoyer la valeur par le biais d'un pointeur vers void
de sorte que cette fonction puisse également être "surchargée" avec C11 _Generic()
et donc de couler et d'écrire dans des types différents pour la sortie.
Bien sûr, l'invocation d'un pointeur vers une fonction a un surcoût en termes de performances, et je suppose qu'il est bien plus lourd que la vérification de la valeur d'une fonction enum
mais à un moment donné, si le nombre de tags est important, je pense qu'il sera plus rapide que switch/case
.
Ma question est la suivante : avez-vous déjà vu cette technique utilisée quelque part ? (Je ne l'ai pas fait, et je ne sais pas si c'est parce que l'application de cette technique dans le monde réel nécessiterait de l'argent. _Generic()
sur la fonction readval, qui nécessite C11, ou si c'est à cause d'un problème que je ne remarque pas pour l'instant). Combien de tags pensez-vous qu'il faudrait avoir pour que le pointeur fonctionne plus rapidement - dans les processeurs Intel actuels - que la fonction switch/case
?