/* Alternative pour remplacer une longue série de if if (val == "cmd1"){ ... }else if (val == "cmd2"){ ... } La solution selone n'est pas plus simple à utiliser qu'un paquet de if et est moins souple. On ne peut pas faire break. Mais on peut passer une variable provenant du parent qui peut être testé dans la boucle (s'il y a une boucle). La solution SELONE découple l'exécution des cas de l'appel. Cela pourrait offrir certains avantages: SELONE sel(...); if (...){ if (...){ sel.test(val); } }else{ sel.test(val); } La solution SELONE pourrait faire certaines validations. Comme on peut déclarer la variable static, ces validations ne coute pas grand chose. On peut vérifier que le cas * est bien à la fin. On ne pas le mettre dans le vecteur opts et appelé la fonction si aucune autre n'est appelé. On pourrait aussi 'compiler' les valeurs pour créer une solution plus rapide. Par exemple, on pourrait mettre les valeurs dans des string c++ qui sont plus rapide pour comparer parce qu'elle contiennent la longueur. On pourrait trier les valeurs dans le tableau et avoir un accès indexés. On peut ajouter de l'instrumentation à SELONE sans pertuber le code appelant. */ #include #include #include #include #include #include #include #include #include "getnow.h" #include using namespace std; void selone_foo(); extern long selone_foo_val; template void selone(PARAM_STRING val, PARAM_STRING opt1, F f) { if (is_eq(opt1,"*") || is_eq(val,opt1)){ f(); } } template void selone(PARAM_STRING val, PARAM_STRING opt1, F f, TS ... ts) { static_assert ((sizeof...(ts)%2) == 0,"fonction selone: Les arguments vont par paires"); if (is_eq(val,opt1)){ f(); }else{ selone(val,ts...); } } using flambda = function; #if 0 template void selone_fill (vector> &opts, flambda &inval, PARAM_STRING opt, F f){ if (is_eq(opt,"*")){ inval = f; }else{ opts.emplace_back(opt,f); } } template void selone_fill (vector> &opts, flambda &inval, PARAM_STRING opt, F f, TS ... ts){ selone_fill (opts,inval,opt,f); selone_fill (opts,inval,ts...); } #endif bool operator < (PARAM_STRING p1, PARAM_STRING p2) { return strcmp(p1.ptr,p2.ptr) < 0; } template class SELONE{ vector> opts; map mapopts; flambda inval; template void fill (PARAM_STRING opt, FF f){ if (is_eq(opt,"*")){ inval = f; }else{ opts.emplace_back(opt,f); mapopts[opt] = f; } } template void fill (PARAM_STRING opt, FF f, TTS ... ts){ fill (opt,f); fill (ts...); } public: SELONE(PARAM_STRING opt1, F f, TS ...ts){ fill (opt1,f,ts...); //selone_fill (opts,inval,opt1,f,ts...); } void test(PARAM_STRING val) const { #if 1 auto it = mapopts.find(val); if (it == mapopts.end()){ inval(); }else{ it->second(); } #else bool found = false; for (auto &o:opts){ if (is_eq(o.first,val)){ o.second(); found = true; break; } } if (!found && inval) inval(); #endif } }; int main (int argc, char *argv[]) { glocal int ret = -1; glocal bool perf = false; glocal const char *opt = "optv19"; glocal int nbrep = 1000000; glocal.ret = (argc,argv); setproginfo ("","0.0","..."); setarg ('p',"perf","Test performance",glocal.perf,false); setarg ('n',"nbrep","Nombre de répétition",glocal.nbrep,false); setarg ('o',"opt","Option cherchée",glocal.opt,false); int ret = -1; if (glocal.perf){ ret = 0; printf ("Test de performance, nbrep=%d\n",glocal.nbrep); { static SELONE sel( #include "/tmp/selone-opts.h" ); auto start = getnow(); selone_foo_val = 0; for (int i=0; i int ret = -1; static SELONE sel("v1",[]() { printf ("sel v1\n"); } ,"v2",[]() { printf ("sel v2\n"); } ,"v3",[&ret]() { printf ("sel v3, ret = 0\n"); ret = 0; } ,"v4",[](){ printf ("sel v4\n"); } ,"*",[](){ printf ("sel inval\n"); } ,"v5",[](){ printf ("sel v5\n"); } ); for (int i=0; i return glocal.ret; }