public
Last active

Visitor pattern for boost::any in C++11

  • Download Gist
any_visitor.cpp
C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
#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;
}
}
output.txt
1 2 3
fa(1)
fb(abc())
no visitor registered

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.