#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;
}