#include <typeinfo>
#include <iostream>
using namespace std;
template <typename typed, int i> 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:0> next;
};
struct smth
{
template <int i> struct key_t {};
template <int i> void get(key_t<i>) {}
int x; int get(key_t<1>) { return this->x; }
double y; double get(key_t<2>) { return this->y; }
template <int i> auto get() -> decltype(this->get(key_t<i>())) { return this->get(key_t<i>()); }
};
int main()
{
smth s = {1, 2.5};
cout.setf(ios::boolalpha);
cout << s.x << ' ' << s.y << endl;
cout << s.get<1>() << ' ' << s.get<2>() << endl;
cout << endl;
cout << enumerate<smth, 1>::get(s) << ' ' << enumerate<smth, 1>::has_next << endl;
cout << enumerate<smth, 1>::next::get(s) << ' ' << enumerate<smth, 1>::next::has_next << endl;
return 0;
}
I2luY2x1ZGUgPHR5cGVpbmZvPgojaW5jbHVkZSA8aW9zdHJlYW0+Cgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKdGVtcGxhdGUgPHR5cGVuYW1lIHR5cGVkLCBpbnQgaT4gc3RydWN0IGVudW1lcmF0ZQp7CglzdGF0aWMgYXV0byBnZXQodHlwZWQgeCkgLT4gZGVjbHR5cGUoeC50ZW1wbGF0ZSBnZXQ8aT4oKSkgeyByZXR1cm4geC50ZW1wbGF0ZSBnZXQ8aT4oKTsgfTsKCWNvbnN0IHN0YXRpYyBib29sIGhhc19uZXh0ID0gIWlzX3NhbWU8ZGVjbHR5cGUodHlwZWQoKS50ZW1wbGF0ZSBnZXQ8aSsxPigpKSwgdm9pZD46OnZhbHVlOwoJdHlwZWRlZiBlbnVtZXJhdGU8dHlwZWQsIGhhc19uZXh0P2krMTowPiBuZXh0Owp9OwoKc3RydWN0IHNtdGgKewoJdGVtcGxhdGUgPGludCBpPiBzdHJ1Y3Qga2V5X3Qge307CgkKCXRlbXBsYXRlIDxpbnQgaT4gdm9pZCBnZXQoa2V5X3Q8aT4pIHt9CgkKCWludCB4OyBpbnQgZ2V0KGtleV90PDE+KSB7IHJldHVybiB0aGlzLT54OyB9Cglkb3VibGUgeTsgZG91YmxlIGdldChrZXlfdDwyPikgeyByZXR1cm4gdGhpcy0+eTsgfQoJCgl0ZW1wbGF0ZSA8aW50IGk+IGF1dG8gZ2V0KCkgLT4gZGVjbHR5cGUodGhpcy0+Z2V0KGtleV90PGk+KCkpKSB7IHJldHVybiB0aGlzLT5nZXQoa2V5X3Q8aT4oKSk7IH0KfTsKCmludCBtYWluKCkKewoJc210aCBzID0gezEsIDIuNX07CgkKCWNvdXQuc2V0Zihpb3M6OmJvb2xhbHBoYSk7CgkKCWNvdXQgPDwgcy54IDw8ICcgJyA8PCBzLnkgPDwgZW5kbDsKCWNvdXQgPDwgcy5nZXQ8MT4oKSA8PCAnICcgPDwgcy5nZXQ8Mj4oKSA8PCBlbmRsOwoJY291dCA8PCBlbmRsOwoJY291dCA8PCBlbnVtZXJhdGU8c210aCwgMT46OmdldChzKSA8PCAnICcgPDwgZW51bWVyYXRlPHNtdGgsIDE+OjpoYXNfbmV4dCA8PCBlbmRsOwoJY291dCA8PCBlbnVtZXJhdGU8c210aCwgMT46Om5leHQ6OmdldChzKSA8PCAnICcgPDwgZW51bWVyYXRlPHNtdGgsIDE+OjpuZXh0OjpoYXNfbmV4dCA8PCBlbmRsOwoJCglyZXR1cm4gMDsKfQ==