Je sépare cette question de celle concernant ajout aux macros CPP :
Est-ce que quelqu'un ici a utilisé le Préprocesseur Boost les types de données de la bibliothèque pour implémenter quelque chose comme la macro X ?
Je sépare cette question de celle concernant ajout aux macros CPP :
Est-ce que quelqu'un ici a utilisé le Préprocesseur Boost les types de données de la bibliothèque pour implémenter quelque chose comme la macro X ?
Je viens de regarder ce qu'est un X-Macro est censé être et je pense que j'ai fait quelque chose comme ce que vous demandez.
Ce que je voulais faire, c'était de prendre en charge facilement et rapidement la sérialisation pour une série de classes assez similaires. Le problème que j'ai rencontré est que je devais convertir certaines informations d'exécution (un int) en un type de compilation (une classe) pour pouvoir effectuer ma sérialisation. J'aurais pu écrire quelques instructions de cas pour faire le travail, mais cela signifiait que je devais mettre à jour plusieurs fonctions chaque fois que je voulais ajouter une classe.
Pour contourner ce problème, j'ai d'abord défini une séquence de tuples contenant la cartographie :
#define WIN_MESSAGE_TYPE_SEQ \
((EM_REPLACESEL, em_replacesel))((WM_CHAR, wm_char)) //...
Les noms en majuscules sont des définitions qui contiennent un int et les noms en minuscules sont des classes que j'ai définies ailleurs.
Je peux alors utiliser cette séquence en conjonction avec certaines des Préprocesseurs Boost pour générer toutes sortes de codes pour moi. Par exemple, pour obtenir une déclaration directe des classes, je peux simplement faire ceci :
#define WIN_MESSAGE_TYPE_BUILD_MACRO(r, _data_, _elem_) \
class BOOST_PP_TUPLE_ELEM(2,1,_elem_);
BOOST_PP_SEQ_FOR_EACH(WIN_MESSAGE_TYPE_BUILD_MACRO, BOOST_PP_NIL, WIN_MESSAGE_TYPE_SEQ)
#undef WIN_MESSAGE_TYPE_BUILD_MACRO
Pour faire la correspondance entre le temps d'exécution et le temps de compilation, je génère une série d'instructions de cas comme ceci :
#define WIN_MESSAGE_TYPE_BUILD_MACRO(r, _data_, _elem_) \
case BOOST_PP_TUPLE_ELEM(2,0,_elem_): return win_message_serializer<BOOST_PP_TUPLE_ELEM(2,1,_elem_)>::serialize(msg, o_arch);
template <typename Archive>
void serialize_win_message (p_win_message_base msg, Archive& o_arch) {
message_type_t message_type = msg->type();
switch (message_type) {
// This will generate a series of case statement for each message type that will invoke
// the serializer for the correct types.
BOOST_PP_SEQ_FOR_EACH(WIN_MESSAGE_TYPE_BUILD_MACRO, BOOST_PP_NIL, WIN_MESSAGE_TYPE_SEQ)
default: //...
};
}
#undef WIN_MESSAGE_TYPE_BUILD_MACRO
Le code entier implique un peu plus que cela, mais cela devrait vous donner une idée de la façon de générer du code en utilisant les préprocesseurs Boost. Dans mon exemple, je peux rapidement et facilement ajouter le support de la sérialisation pour une classe en mettant simplement à jour ma séquence.
Notez que l'utilisation du préprocesseur Boost ne produit pas un code très lisible. J'essaie donc de garder la macro utilisée par le for each macro aussi simple que possible. Je ne serais pas non plus surpris que quelqu'un, quelque part, ait une solution plus élégante à ce problème. C'est juste ce que j'ai trouvé pour un projet personnel où la complexité supplémentaire ne me dérange pas.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.