Dans mes projets j'utilise exhaustivement boost::any
et boost::variant
. Pour cela, une routine de conversion générale de boost::any
à boost::variant
a été conçue dans ma précédente question Generic function to convert boost::any to boost::variant. Merci beaucoup aux personnes qui m'ont aidé.Boost tout à Boost Variant en utilisant le préprocesseur Boost
La solution trouvée a fonctionné pour moi sans aucun problème, mais avait un sérieux inconvénient. Le gonflement du code produit par la solution entièrement modélisée peut être prohibitif et parfois inutile pour une simple conversion. (Je n'ai pas mentionné les temps de compilation.)
Maintenant j'ai eu l'idée de laisser la spécialisation de template fonctionner pour les conversions faciles (non générales), mais j'ai trouvé le code nécessaire fastidieux et sujet aux erreurs à taper. Surtout, si l'on doit faire cette tâche encore et encore.
L'extrait de code suivant illustre le problème. Image que dans une application typique on pourrait avoir jusqu'à 20 types ou plus!
#include <boost/preprocessor.hpp>
#include <boost/variant.hpp>
#include <boost/any.hpp>
#include <boost/optional.hpp>
#include <iostream>
template<typename VARIANT>
boost::optional<VARIANT> anyToVariant(const boost::any& any) {
boost::optional<VARIANT> ret;
// General implementation omitted.
// The implementation is lengthy and produces an enormous code bloat. In some cases it is the best solution.
return ret;
}
// Specialized Template reduces code bloat. But is error-prone to type write for every new variant type.
template<>
boost::optional <boost::variant<int, double, std::string>> anyToVariant(const boost::any& any) {
boost::optional<boost::variant<int, double, std::string>> ret;
if (any.type() == typeid(int)) {
ret = boost::any_cast<int>(any);
}
if (any.type() == typeid(double)) {
ret = boost::any_cast<double>(any);
}
if (any.type() == typeid(std::string)) {
ret = boost::any_cast<std::string>(any);
}
return ret;
}
// Should be implemented with boost preprocessor
#define BOOST_ANY_TO_VARIANT(TypeList)
// Better would be a macro like this
BOOST_ANY_TO_VARIANT(int, double, std::string); // Create the above template specialization
int main() {
boost::variant<int, double, std::string> v;
boost::any x = 4;
v=*anyToVariant<boost::variant<int, double, std::string>>(x);
}
Une meilleure solution serait bien sûr une macro, mais malheureusement je n'étais pas en mesure de mettre en œuvre cette macro avec boost-preprocessor
. Je n'ai toujours pas les compétences, mais je suis sûr que cela pourrait être fait.
Quelqu'un avec expérience dans boost-preprocessor
peut-il m'aider avec mon problème?
La meilleure solution que je pouvais imaginer serait une macro comme ce qui suit:
#define BOOST_ANY_TO_VARIANT(VariantType) \
// Magic?
typedef boost::variant<int, std::string, double> MyVariant;
BOOST_ANY_TO_VARIANT(MyVariant)
Mais je doute que cette solution est réalisable.
Donc, pour être clair, l'objectif de la macro est de générer la définition de la spécialisation du modèle, * pas * convertir un 'boost :: any' sur place? – Quentin
Vous l'avez. La macro devrait simplement générer le code ci-dessus. – Aleph0