#ifndef UTILITIES_H
#define UTILITIES_H
#include <tuple>
#include <utility>
#include <functional>
#include <map>
// This comes from here:
// http://stackoverflow.com/questions/4988939/how-do-boostvariant-and-boostany-work
// Currently not using this, but it might be useful in the future and explains idea behine how boost::any works
struct f_any
{
f_any() : ptr() {}
~f_any() { delete ptr; }
bool valid() const { return ptr != 0; }
void f() { assert(ptr); ptr->f(); }
struct placeholder
{
virtual ~placeholder() {}
virtual void f() const = 0;
};
template < typename T >
struct impl : placeholder
{
impl(T const& t) : val(t) {}
void f() const { val.f(); }
T val;
};
// ptr can now point to the entire family of
// struct types generated from impl<T>
placeholder * ptr;
template < typename T >
f_any(T const& t) : ptr(new impl<T>(t)) {}
// assignment, etc...
};
// The idea comes from here:
// http://stackoverflow.com/questions/1197106/static-constructors-in-c-need-to-initialize-private-static-objects
// Currently this isn't being used, but it is a neat solution and for some reason it was low in the
// voted for solutions. It appears quite low on the stackoverflow page. I actually quite like it.
// Usage: static void StaticTest() {
// static_constructor<&Test::StaticTest>::c;
// // <insert code you actually want to run once at startup here>
// }
template<void(*ctor)()>
struct static_constructor
{
struct constructor { constructor() { ctor(); } };
static constructor c;
};
template<void(*ctor)()>
typename static_constructor<ctor>::constructor static_constructor<ctor>::c;
// The idea behind this comes from here:
// http://stackoverflow.com/questions/1198260/iterate-over-tuple
template<typename V, typename T, std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
for_each(V& v, T obj, std::map<std::string, std::function<void(V&, T&)> >& fmap, std::tuple<Tp...> &) // Unused arguments are given no names.
{ }
template<typename V, typename T, std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
for_each(V& v, T obj, std::map<std::string, std::function<void(V&, T&)> >& fmap, std::tuple<Tp...>& t)
{
const char* name = std::get<I>(t);
auto getRef = std::get<I+1>(t);
auto lambda = [name,getRef](V& v, T& obj){ v.Visit(name, getRef(obj)); };
fmap.insert(std::make_pair(std::string(name), lambda));
for_each<V, T, I + 2, Tp...>(v, obj, fmap, t);
}
#endif // UTILITIES_H