Bonjour à tous,
Je voudrais écrire l'équivalent d'une boucle for avec break en méta-programmation:
j'ai une liste de types:
sur laquelle je vais appliquer un foncteur au run-time:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 #include <boost/fusion/include/vector.hpp> #include <boost/mpl/at.hpp> using namespace boost::fusion; typedef vector<int, double, std::string> mes_types;
je voudrais donc pouvoir itérer sur ma liste de types, appliquer mon foncteur dessus, mémoriser les résultats de l'application du foncteur et m’arrêter lorsque le résultat du foncteur rencontre une condition particulière; fonctionnellement un truc dans ce goût là:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 struct mon_foncteur { template<typename T> T operator()(T const& src) { return src + 2; } template<> std::string operator()(std::string const& src) { return src + "yz"; } };
avec check une méthode qui vérifie le résultat du foncteur, par exemple
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13 bool function(mes_types const& types, mes_types& result) { mon_foncteur f; for(size_t i=0; i<result_of::size<mes_types>::type::value; ++i) { //on applique le foncteur et on récupère les résultats at_c<i>(result) = f(at_c<i>(types)); //problème de compilation: i est n'est pas une constante connue à la compilation if(check(at_c<i>(result)) return false; //le check a échoué, on arrête la boucle } return true; //ok tout s'est bien passé }
Ce code ne compile pas car il faudrait indiquer au compilateur que la boucle peut être déroulée à la compilation et qu'il n'y a donc pas de problèmes à appeler at_c<i>. Voilà je sèche un peu, je suis parti sur du boost mais si vous avez une solution en C++ "classique" je suis preneur.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 template<typename T> bool check(T const& t) { return t%2 == 0; }; template<> bool check<std::string>(std::string const& s) { return s.size()%2 == 0; };
P.S. l'exemple "complet" presque compilable:
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 #include <string> #include <boost/fusion/include/vector.hpp> #include <boost/fusion/include/size.hpp> #include <boost/fusion/include/make_vector.hpp> #include <boost/mpl/at.hpp> using namespace boost::fusion; typedef vector<int, double, std::string> mes_types; struct mon_foncteur { template<typename T> T operator()(T const& src) { return src + 2; } template<> std::string operator()(std::string const& src) { return src + "yz"; } }; template<typename T> bool check(T const& t) { return t%2 == 0; }; template<> bool check<std::string>(std::string const& s) { return s.size()%2 == 0; }; bool function(mes_types const& types, mes_types& result) { mon_foncteur f; for(size_t i=0; i<result_of::size<mes_types>::type::value; ++i) { at_c<i>(result) = f(at_c<i>(types)); if(check(at_c<i>(result)) return false; //le foncteur a echoué } return true; } int main() { //dans l'exemple suivant, on ne doit calculer que f(0) et f(11) et pas f("abcd") mes_types types(make_vector(0, 11, "abcd")); mes_types result; function(types, result); return 0; }
Partager