#include <iostream>
#include <string>
 
namespace memenum
{
    template <int Counter>
	struct member_iterator : member_iterator<Counter - 1> { static int const value = Counter; };
	template <>
	struct member_iterator<0> { static int const value = 0; };
 
	template <class This, class Op>
	void call_for_members(This*, member_iterator<__COUNTER__>, Op const&) { }
 
	template <class T>
	struct member_wrapper
	{
		T value;
		member_wrapper(T const &v) : value(v) { }
	};
 
	#define DEFINE_MEMBER(type, memname, ...) \
		struct _##memname##_type : ::memenum::member_wrapper<type> \
		{ \
			static int const counter = __COUNTER__; \
			_##memname##_type() : ::memenum::member_wrapper<type>(__VA_ARGS__) { } \
			char const* name() const { return #memname; } \
		} memname; \
		template <class This, class Op> \
		friend void call_for_members(This *self, ::memenum::member_iterator<_##memname##_type::counter> i, Op const &op, typename This::_##memname##_type* = nullptr) \
		{ \
			call_for_members(self, ::memenum::member_iterator<_##memname##_type::counter - 1>(), op); \
			op(self->memname); \
		}
 
	#define MAKE_MEMBER_ITERATOR() ::memenum::member_iterator<__COUNTER__>()
 
} // namespace
 
namespace test
{
 
	struct foo
	{
		DEFINE_MEMBER(int, a, 2);
		DEFINE_MEMBER(float, b, 2.5f);
 
	public:
		struct Printer
		{
			template <class T>
			void operator ()(T &member) const
			{
				std::cout << member.name() << " = " << member.value << std::endl;
			}
		};
		void print() const
		{
			call_for_members(this, MAKE_MEMBER_ITERATOR(), Printer());
		}
 
		struct Multiplier
		{
			int factor;
 
			template <class T>
			void operator ()(T &member) const
			{
				member.value *= factor;
			}
		};
 
		void multiply(int factor)
		{
			Multiplier multi = { factor };
			call_for_members(this, MAKE_MEMBER_ITERATOR(), multi);
		}
	};
 
	struct bar
	{
		DEFINE_MEMBER(char, c, 'd');
		DEFINE_MEMBER(std::string, d, "hello world");
 
	public:
		struct Printer
		{
			template <class T>
			void operator ()(T &member) const
			{
				std::cout << member.name() << " = " << member.value << std::endl;
			}
		};
		void print() const
		{
			call_for_members(this, MAKE_MEMBER_ITERATOR(), Printer());
		}
	};
 
} // namespace
 
int main()
{
	test::foo test1;
	test1.print();
	test1.multiply(5);
	test1.print();
 
	const test::bar test2;
	test2.print();
}
 
				I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8c3RyaW5nPgoKbmFtZXNwYWNlIG1lbWVudW0KewogICAgdGVtcGxhdGUgPGludCBDb3VudGVyPgoJc3RydWN0IG1lbWJlcl9pdGVyYXRvciA6IG1lbWJlcl9pdGVyYXRvcjxDb3VudGVyIC0gMT4geyBzdGF0aWMgaW50IGNvbnN0IHZhbHVlID0gQ291bnRlcjsgfTsKCXRlbXBsYXRlIDw+CglzdHJ1Y3QgbWVtYmVyX2l0ZXJhdG9yPDA+IHsgc3RhdGljIGludCBjb25zdCB2YWx1ZSA9IDA7IH07CgoJdGVtcGxhdGUgPGNsYXNzIFRoaXMsIGNsYXNzIE9wPgoJdm9pZCBjYWxsX2Zvcl9tZW1iZXJzKFRoaXMqLCBtZW1iZXJfaXRlcmF0b3I8X19DT1VOVEVSX18+LCBPcCBjb25zdCYpIHsgfQoKCXRlbXBsYXRlIDxjbGFzcyBUPgoJc3RydWN0IG1lbWJlcl93cmFwcGVyCgl7CgkJVCB2YWx1ZTsKCQltZW1iZXJfd3JhcHBlcihUIGNvbnN0ICZ2KSA6IHZhbHVlKHYpIHsgfQoJfTsKCgkjZGVmaW5lIERFRklORV9NRU1CRVIodHlwZSwgbWVtbmFtZSwgLi4uKSBcCgkJc3RydWN0IF8jI21lbW5hbWUjI190eXBlIDogOjptZW1lbnVtOjptZW1iZXJfd3JhcHBlcjx0eXBlPiBcCgkJeyBcCgkJCXN0YXRpYyBpbnQgY29uc3QgY291bnRlciA9IF9fQ09VTlRFUl9fOyBcCgkJCV8jI21lbW5hbWUjI190eXBlKCkgOiA6Om1lbWVudW06Om1lbWJlcl93cmFwcGVyPHR5cGU+KF9fVkFfQVJHU19fKSB7IH0gXAoJCQljaGFyIGNvbnN0KiBuYW1lKCkgY29uc3QgeyByZXR1cm4gI21lbW5hbWU7IH0gXAoJCX0gbWVtbmFtZTsgXAoJCXRlbXBsYXRlIDxjbGFzcyBUaGlzLCBjbGFzcyBPcD4gXAoJCWZyaWVuZCB2b2lkIGNhbGxfZm9yX21lbWJlcnMoVGhpcyAqc2VsZiwgOjptZW1lbnVtOjptZW1iZXJfaXRlcmF0b3I8XyMjbWVtbmFtZSMjX3R5cGU6OmNvdW50ZXI+IGksIE9wIGNvbnN0ICZvcCwgdHlwZW5hbWUgVGhpczo6XyMjbWVtbmFtZSMjX3R5cGUqID0gbnVsbHB0cikgXAoJCXsgXAoJCQljYWxsX2Zvcl9tZW1iZXJzKHNlbGYsIDo6bWVtZW51bTo6bWVtYmVyX2l0ZXJhdG9yPF8jI21lbW5hbWUjI190eXBlOjpjb3VudGVyIC0gMT4oKSwgb3ApOyBcCgkJCW9wKHNlbGYtPm1lbW5hbWUpOyBcCgkJfQoKCSNkZWZpbmUgTUFLRV9NRU1CRVJfSVRFUkFUT1IoKSA6Om1lbWVudW06Om1lbWJlcl9pdGVyYXRvcjxfX0NPVU5URVJfXz4oKQoKfSAvLyBuYW1lc3BhY2UKCm5hbWVzcGFjZSB0ZXN0CnsKCQoJc3RydWN0IGZvbwoJewoJCURFRklORV9NRU1CRVIoaW50LCBhLCAyKTsKCQlERUZJTkVfTUVNQkVSKGZsb2F0LCBiLCAyLjVmKTsKCglwdWJsaWM6CgkJc3RydWN0IFByaW50ZXIKCQl7CgkJCXRlbXBsYXRlIDxjbGFzcyBUPgoJCQl2b2lkIG9wZXJhdG9yICgpKFQgJm1lbWJlcikgY29uc3QKCQkJewoJCQkJc3RkOjpjb3V0IDw8IG1lbWJlci5uYW1lKCkgPDwgIiA9ICIgPDwgbWVtYmVyLnZhbHVlIDw8IHN0ZDo6ZW5kbDsKCQkJfQoJCX07CgkJdm9pZCBwcmludCgpIGNvbnN0CgkJewoJCQljYWxsX2Zvcl9tZW1iZXJzKHRoaXMsIE1BS0VfTUVNQkVSX0lURVJBVE9SKCksIFByaW50ZXIoKSk7CgkJfQoKCQlzdHJ1Y3QgTXVsdGlwbGllcgoJCXsKCQkJaW50IGZhY3RvcjsKCgkJCXRlbXBsYXRlIDxjbGFzcyBUPgoJCQl2b2lkIG9wZXJhdG9yICgpKFQgJm1lbWJlcikgY29uc3QKCQkJewoJCQkJbWVtYmVyLnZhbHVlICo9IGZhY3RvcjsKCQkJfQoJCX07CgoJCXZvaWQgbXVsdGlwbHkoaW50IGZhY3RvcikKCQl7CgkJCU11bHRpcGxpZXIgbXVsdGkgPSB7IGZhY3RvciB9OwoJCQljYWxsX2Zvcl9tZW1iZXJzKHRoaXMsIE1BS0VfTUVNQkVSX0lURVJBVE9SKCksIG11bHRpKTsKCQl9Cgl9OwoKCXN0cnVjdCBiYXIKCXsKCQlERUZJTkVfTUVNQkVSKGNoYXIsIGMsICdkJyk7CgkJREVGSU5FX01FTUJFUihzdGQ6OnN0cmluZywgZCwgImhlbGxvIHdvcmxkIik7CgoJcHVibGljOgoJCXN0cnVjdCBQcmludGVyCgkJewoJCQl0ZW1wbGF0ZSA8Y2xhc3MgVD4KCQkJdm9pZCBvcGVyYXRvciAoKShUICZtZW1iZXIpIGNvbnN0CgkJCXsKCQkJCXN0ZDo6Y291dCA8PCBtZW1iZXIubmFtZSgpIDw8ICIgPSAiIDw8IG1lbWJlci52YWx1ZSA8PCBzdGQ6OmVuZGw7CgkJCX0KCQl9OwoJCXZvaWQgcHJpbnQoKSBjb25zdAoJCXsKCQkJY2FsbF9mb3JfbWVtYmVycyh0aGlzLCBNQUtFX01FTUJFUl9JVEVSQVRPUigpLCBQcmludGVyKCkpOwoJCX0KCX07Cgp9IC8vIG5hbWVzcGFjZQoKaW50IG1haW4oKQp7Cgl0ZXN0Ojpmb28gdGVzdDE7Cgl0ZXN0MS5wcmludCgpOwoJdGVzdDEubXVsdGlwbHkoNSk7Cgl0ZXN0MS5wcmludCgpOwoKCWNvbnN0IHRlc3Q6OmJhciB0ZXN0MjsKCXRlc3QyLnByaW50KCk7Cn0K