Last active
December 19, 2015 01:28
-
-
Save mejedi/5875719 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Here be dragons | |
template <typename Visitor> | |
struct VisitorBase { | |
template<typename T> | |
void visit(T &c) { | |
T::template VisitorContinuation__<Visitor,0>::invoke(static_cast<Visitor&>(*this), c); | |
} | |
}; | |
#define STRUCT(name) \ | |
struct name { \ | |
typedef name ThisType__; \ | |
template<typename Visitor, int Tier> \ | |
struct VisitorContinuation__ { \ | |
static void invoke(Visitor &visitor, ThisType__ &c) {} \ | |
}; \ | |
enum { COUNTER_BASE__ = __COUNTER__ }; // technically this is ODR violation but we can probably get away with it | |
#define FIELD(name, type) \ | |
type name; \ | |
template<typename Visitor> \ | |
struct VisitorContinuation__<Visitor,(__COUNTER__-COUNTER_BASE__-1)/2> { \ | |
static void invoke(Visitor &visitor, ThisType__ &c) { \ | |
visitor.visit_field(# name, c.name); \ | |
VisitorContinuation__<Visitor,(__COUNTER__-COUNTER_BASE__)/2>::invoke(visitor, c); \ | |
} \ | |
}; | |
#define END_STRUCT \ | |
}; | |
// Here be dragons no longer | |
#include <cstdio> | |
struct Printer: VisitorBase<Printer> | |
{ | |
void visit_field(const char *name, int val) { | |
::printf("%s %d\n", name, val); | |
} | |
void visit_field(const char *name, float val) { | |
::printf("%s %.3f\n", name, val); | |
} | |
}; | |
STRUCT(Dummy) | |
FIELD(foo, int) | |
FIELD(bar, int) | |
END_STRUCT | |
STRUCT(Point3D) | |
FIELD(x, float) | |
FIELD(y, float) | |
FIELD(z, float) | |
END_STRUCT | |
int main() | |
{ | |
Dummy dummy; | |
dummy.foo = 42; | |
dummy.bar = 0; | |
Point3D point; | |
point.x = 1.f; | |
point.y = -1.f; | |
point.z = .5f; | |
Printer printer; | |
printer.visit(dummy); | |
printer.visit(point); | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment