#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