Skip to content

Instantly share code, notes, and snippets.

@pyrtsa
Created June 17, 2012 19:09
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save pyrtsa/2945472 to your computer and use it in GitHub Desktop.
Save pyrtsa/2945472 to your computer and use it in GitHub Desktop.
Visitor pattern for boost::any in C++11
#include <boost/any.hpp>
#include <unordered_map>
#include <functional>
#include <iostream>
#include <vector>
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()(std::reference_wrapper<T> a,
std::reference_wrapper<T> b) const {
return a.get() == b.get();
}
};
struct any_visitor {
using type_info_ref = std::reference_wrapper<std::type_info const>;
using function = std::function<void(boost::any&)>;
std::unordered_map<type_info_ref, function, type_info_hash, equal_ref> fs;
template <typename T>
void insert_visitor(std::function<void(T&)> f) {
fs.insert(std::make_pair(
std::ref(typeid(T)),
function([&f](boost::any & x) { f(boost::any_cast<T&>(x)); })));
}
bool operator()(boost::any & x) {
auto it = fs.find(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;
}
}
fa(1)
fb(abc())
no visitor registered
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment