In meinen Projekten verwende ich boost::any
und boost::variant
erschöpfend. Dazu wurde in meiner vorherigen Frage Generic function to convert boost::any to boost::variant eine allgemeine Umwandlungsroutine von boost::any
zu boost::variant
entwickelt. Vielen Dank an die Leute, die mir geholfen haben.Boost Any to Boost Variante mit Boost Preprocessor
Die gefundene Lösung funktionierte bei mir ohne Probleme, hatte aber einige gravierende Nachteile. Der durch die vollständig templatisierte Lösung erzeugte Code-Blop könnte prohibitiv sein und manchmal für eine einfache Umwandlung unnötig sein. (Ich habe die Kompilierungszeiten nicht erwähnt.)
Jetzt kam ich auf die Idee, die Template-Spezialisierung für die einfachen (nicht-allgemeinen) Konvertierungen arbeiten zu lassen, aber ich fand den notwendigen Code mühsam und fehleranfällig zu tippen. Vor allem, wenn man diese Aufgabe immer wieder machen muss.
Das folgende Code-Snippet veranschaulicht das Problem. Stellen Sie sich vor, dass Sie in einer typischen Anwendung bis zu 20 oder mehr Typen haben können!
#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);
}
Eine bessere Lösung wäre ein Makro natürlich sein, aber leider war ich nicht in der Lage diesen Makro mit boost-preprocessor
zu implementieren. Mir fehlen immer noch die Fähigkeiten, aber ich bin mir sicher, dass es getan werden könnte.
Kann jemand mit Erfahrung in boost-preprocessor
mir mit meinem Problem helfen?
#define BOOST_ANY_TO_VARIANT(VariantType) \
// Magic?
typedef boost::variant<int, std::string, double> MyVariant;
BOOST_ANY_TO_VARIANT(MyVariant)
Aber ich bezweifle, dass diese Lösung erreichbar ist:
Die beste Lösung, die ich vorstellen könnte ein Makro wie folgt wäre.
Also, nur klar zu sein, ist das Ziel des Makros ist die Definition der Template-Spezialisierung zu erzeugen, * nicht * einen 'boost :: any' an Ort und Stelle konvertieren? – Quentin
Sie haben es verstanden. Das Makro sollte nur den obigen Code generieren. – Aleph0