boucle for et break métaprogrammation
Bonjour à tous,
Je voudrais écrire l'équivalent d'une boucle for avec break en méta-programmation:
j'ai une liste de types:
Code:
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; |
sur laquelle je vais appliquer un foncteur au run-time:
Code:
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"; }
}; |
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:
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é
} |
avec check une méthode qui vérifie le résultat du foncteur, par exemple
Code:
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;
}; |
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.
P.S. l'exemple "complet" presque compilable:
Code:
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;
} |