Ceci étant dit, si tu travailles sur base d'une énumération (reprenons l'idée des seules fonction trigono, par facilité) proche deLe fait de travailler avec une classe prenant, pour la cause, une forme proche de
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 enum WichFunction{ sinus, cosinus, tangeante, /* ...*/ MAX // TRES important, tu verras pourquoi ensuite };Alors, je sens que tu vas m'objecter que c'est sensiblement la même chose que d'avoir un switch, qu'il soit dans le constructeur ou dans la fonction... Sauf que :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 class Algo{ /* je suis un gros fade, j'ai horreur de me répéter sur des noms de type trop complexes */ using tab_t = std::vector<double (*) (double>; /* quitte à ne pas respecter l'OCP, respectons le SRP */ static tab_t const & allFunctions(){ static const tab_t funcs{&std::sin &std::cos, &std::tan /*, ... */}; /* on se permet d'engueuler l'implémenteur si le nombre de fonctions indiquées * ne correspond pas au nombre de valeur énumérées */ assert(funcs.size() == MAX && "Implementor!!! Please do your job !!!"); return funcs; } public: /* chaque fois que l'on veut utiliser l'algorithme, il faut préciser la fonction qui sera utilisée */ Algo(WichFunction f):f_{f}{ /* L'utilisateur est un imbécile distrait qui pourrait nous servir un Algo bad(static_cast<WichFunction>(127); */ assert(f< MAX && "bad function requested"); } double exec(double d) const{ return allFunctions()[f_](d); } }
1- D'un point de vue conceptuel, on se rajoute un garde fous: on ne peut pas ajouter une valeur énumérée (avant MAX, ca va de soi) ou une fonction sans rajouter son pendant de "l'autre coté".
J'aurais, bien sur, préféré une erreur de compilation, à ce sujet, ce qui devrait être possible, vu que les valeurs énumérés sont des constantes de compilation, mais, si tu oublies l'un des deux, le premier test qui utilisera Algo te rappellera à l'ordre
Bien sur, tu pourrais demander au compilateur de te lancer un avertissement sur les valeurs énumérées absentes de ton switch... case, mais, qui s'en inquièterait
2- Sans préjuger le moins du monde des optimisations que peut faire le compilateur sur un switch ... case, l'utilisation d'un tableau limite l'action à ... un décallage d'adresse dans le tableau, sans test pour savoir quelle valeur nous intéresse.
Toi qui veut des performances, tu sera servi, car à ce titre, tu ne trouveras sans doute pas mieux (même si un bench correct est nécessaire pour confirmer cette assertion )
3- Quitte à ne pas respecter l'OCP (car je peux admettre que ce ne soit pas toujours possible), je limite au maximum la protée de ce non respect.
J'aurais d'ailleurs pu en faire une fonction libre qui ne soit pas déclarée dans le header, et qui serait juste présente dans le fichier d'implémentation, mais j'aurais perdu les possibilités d'inlining
Partager