Ich fand diese https://gist.github.com/2945472, aber ich brauche eine Implementierung, die nicht von C++ 11 abhängt. Ich habe versucht, es zu konvertieren, um nur Boost zu verwenden, aber ich habe einige Probleme.Besuchermuster für boost :: any
Hier ist, was ich kam mit:
#include <boost/any.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/unordered_map.hpp>
struct type_info_hash {
std::size_t operator()(std::type_info const & t) const {
return t.hash_code();
}
};
struct equal_ref {
template <typename T> bool operator()(boost::reference_wrapper<T> a,boost::reference_wrapper<T> b) const {
return a.get() == b.get();
}
};
struct any_visitor {
boost::unordered_map<boost::reference_wrapper<std::type_info const>, boost::function<void(boost::any&)>, type_info_hash, equal_ref> fs;
template <typename T> void insert_visitor(boost::function<void(T)> f) {
try {
fs.insert(std::make_pair(boost::ref(typeid(T)), boost::bind(f, boost::any_cast<T>(boost::lambda::_1))));
} catch (boost::bad_any_cast& e) {
std::cout << e.what() << std::endl;
}
}
bool operator()(boost::any & x) {
boost::unordered_map<boost::reference_wrapper<std::type_info const>, boost::function<void(boost::any&)>, type_info_hash, equal_ref>::iterator it = fs.find(boost::ref(x.type()));
if (it != fs.end()) {
it->second(x);
return true;
} else {
return false;
}
}
};
struct abc {};
void fa(int i) { std::cout << "fa(" << i << ")" << std::endl; }
void fb(abc) { std::cout << "fb(abc())" << std::endl; }
int main() {
any_visitor f;
f.insert_visitor<int>(fa);
f.insert_visitor<abc>(fb);
std::vector<boost::any> xs;
xs.push_back(1);
xs.push_back(abc());
xs.push_back(1.5);
for (auto & x : xs) {
if (!f(x)) std::cout << "no visitor registered" << std::endl;
}
}
Ich bin ein bad_any_cast bekommen, wenn in die Karte eingefügt wird. Soll nicht any_cast nur von it-> second (x) aufgerufen werden? Was mache ich falsch?
Haben Sie überlegt, 'boost :: variant' zu verwenden, für welche Besucher standardmäßig unterstützt werden? Die Verwendung von 'any' setzt voraus, dass die Typen * alles * sein können, also * alle * Typen im Typsystem. 'Variante' geht davon aus, dass es eine Teilmenge der Typen gibt, die Sie im Objekt verwenden möchten. Ein Besucher ist näher an einer "Variante", da die verschiedenen Funktionen definiert werden müssen. –
Meine Absicht ist, dies zu verwenden, um Konfigurationsdateien aus boost :: program_options zu schreiben, die boost :: any verwenden. – Keith