#include <typeinfo>
#include <iostream>
using namespace std;
template <typename typed, int i = 0> struct enumerate
{
static auto get(typed x) -> decltype(x.template get<i>()) { return x.template get<i>(); };
const static bool has_next = !is_same<decltype(typed().template get<i+1>()), void>::value;
typedef enumerate<typed, has_next?i+1:-1> next;
template <template <class> class handler> static void go(typed x)
{
handler<decltype(get(x))>()(get(x));
if (has_next) next::template go<handler>(x);
}
};
template <typename typed> struct enumerate <typed, -1>
{
static void get(typed x) {}
const static bool has_next = false;
typedef enumerate<typed, -1> next;
template <template <class> class handler> static void go(typed x)
{
}
};
#define ENUMERABLE_FIELD(type, name, i) public: type name; \
private: type get(key_t<i>) { return this->name; }
struct smth
{
private: template <int i> struct key_t {};
private: template <int i> void get(key_t<i>) {}
ENUMERABLE_FIELD(int, x, 0)
ENUMERABLE_FIELD(double, y, 1)
public: template <int i> auto get() -> decltype(this->get(key_t<i>())) { return this->get(key_t<i>()); }
};
template <class typed> void print(const typed& t)
{
cout << t << endl;
}
template <class typed> struct pass_to_print
{
void operator () (typed t) { return print(t); }
};
int main()
{
smth s = {1, 2.5};
enumerate<smth>::go<pass_to_print>(s);
return 0;
}
I2luY2x1ZGUgPHR5cGVpbmZvPgojaW5jbHVkZSA8aW9zdHJlYW0+Cgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKdGVtcGxhdGUgPHR5cGVuYW1lIHR5cGVkLCBpbnQgaSA9IDA+IHN0cnVjdCBlbnVtZXJhdGUKewoJc3RhdGljIGF1dG8gZ2V0KHR5cGVkIHgpIC0+IGRlY2x0eXBlKHgudGVtcGxhdGUgZ2V0PGk+KCkpIHsgcmV0dXJuIHgudGVtcGxhdGUgZ2V0PGk+KCk7IH07Cgljb25zdCBzdGF0aWMgYm9vbCBoYXNfbmV4dCA9ICFpc19zYW1lPGRlY2x0eXBlKHR5cGVkKCkudGVtcGxhdGUgZ2V0PGkrMT4oKSksIHZvaWQ+Ojp2YWx1ZTsKCXR5cGVkZWYgZW51bWVyYXRlPHR5cGVkLCBoYXNfbmV4dD9pKzE6LTE+IG5leHQ7CgkKCXRlbXBsYXRlIDx0ZW1wbGF0ZSA8Y2xhc3M+IGNsYXNzIGhhbmRsZXI+IHN0YXRpYyB2b2lkIGdvKHR5cGVkIHgpCgl7CgkJaGFuZGxlcjxkZWNsdHlwZShnZXQoeCkpPigpKGdldCh4KSk7CgkJaWYgKGhhc19uZXh0KSBuZXh0Ojp0ZW1wbGF0ZSBnbzxoYW5kbGVyPih4KTsKCX0KfTsKCnRlbXBsYXRlIDx0eXBlbmFtZSB0eXBlZD4gc3RydWN0IGVudW1lcmF0ZSA8dHlwZWQsIC0xPgp7CglzdGF0aWMgdm9pZCBnZXQodHlwZWQgeCkge30KCWNvbnN0IHN0YXRpYyBib29sIGhhc19uZXh0ID0gZmFsc2U7Cgl0eXBlZGVmIGVudW1lcmF0ZTx0eXBlZCwgLTE+IG5leHQ7CgkKCXRlbXBsYXRlIDx0ZW1wbGF0ZSA8Y2xhc3M+IGNsYXNzIGhhbmRsZXI+IHN0YXRpYyB2b2lkIGdvKHR5cGVkIHgpCgl7Cgl9Cn07CgojZGVmaW5lIEVOVU1FUkFCTEVfRklFTEQodHlwZSwgbmFtZSwgaSkgcHVibGljOiB0eXBlIG5hbWU7IFwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaXZhdGU6IHR5cGUgZ2V0KGtleV90PGk+KSB7IHJldHVybiB0aGlzLT5uYW1lOyB9CgpzdHJ1Y3Qgc210aAp7Cglwcml2YXRlOiB0ZW1wbGF0ZSA8aW50IGk+IHN0cnVjdCBrZXlfdCB7fTsKCXByaXZhdGU6IHRlbXBsYXRlIDxpbnQgaT4gdm9pZCBnZXQoa2V5X3Q8aT4pIHt9CgkKCUVOVU1FUkFCTEVfRklFTEQoaW50LCB4LCAwKQoJRU5VTUVSQUJMRV9GSUVMRChkb3VibGUsIHksIDEpCgkKCXB1YmxpYzogdGVtcGxhdGUgPGludCBpPiBhdXRvIGdldCgpIC0+IGRlY2x0eXBlKHRoaXMtPmdldChrZXlfdDxpPigpKSkgeyByZXR1cm4gdGhpcy0+Z2V0KGtleV90PGk+KCkpOyB9Cn07Cgp0ZW1wbGF0ZSA8Y2xhc3MgdHlwZWQ+IHZvaWQgcHJpbnQoY29uc3QgdHlwZWQmIHQpCnsKCWNvdXQgPDwgdCA8PCBlbmRsOwp9Cgp0ZW1wbGF0ZSA8Y2xhc3MgdHlwZWQ+IHN0cnVjdCBwYXNzX3RvX3ByaW50CnsKCXZvaWQgb3BlcmF0b3IgKCkgKHR5cGVkIHQpIHsgcmV0dXJuIHByaW50KHQpOyB9Cn07CgppbnQgbWFpbigpCnsKCXNtdGggcyA9IHsxLCAyLjV9OwoKCWVudW1lcmF0ZTxzbXRoPjo6Z288cGFzc190b19wcmludD4ocyk7CgkKCXJldHVybiAwOwp9