#include <iostream>
#include <iterator>
struct Foo;
template<typename Type>
struct MemberPtrBase {
virtual ~MemberPtrBase() { }
virtual Type get() const = 0;
virtual MemberPtrBase & set(Type const &) = 0;
};
template<typename Class, typename RealType, typename CommonType>
struct MemberPtr : MemberPtrBase<CommonType> {
public:
MemberPtr(Class * object, RealType(Class::*member))
: m_object(object), m_ptr(member)
{ }
CommonType get() const {
return m_object->*m_ptr;
}
MemberPtr & set(CommonType const & val) {
m_object->*m_ptr = val;
return *this;
}
MemberPtr & operator=(RealType const & val) {
return set(val);
}
operator CommonType() const {
return get();
}
private:
Class * m_object;
RealType (Class::*m_ptr);
};
template<typename Class, typename... Types>
struct MemberIterator {
public:
using CommonType = typename std::common_type<Types...>::type;
public:
MemberIterator(Class & obj, std::size_t idx, Types(Class::*...member))
: m_object(obj), m_index(idx), m_members { new MemberPtr<Class, Types, CommonType>(&obj, member)... }
{ }
MemberPtrBase<CommonType> & operator*() const {
return *m_members[m_index];
}
bool operator==(MemberIterator const & it) const {
return (&m_object == &it.m_object) && (m_index == it.m_index);
}
bool operator!=(MemberIterator const & it) const {
return (&m_object != &it.m_object) || (m_index != it.m_index);
}
MemberIterator & operator++() {
++m_index;
return *this;
}
private:
Class & m_object;
std::size_t m_index;
MemberPtrBase<CommonType> * m_members[sizeof...(Types)];
};
struct Foo {
public:
using iterator = MemberIterator<Foo, int, int, int, int>;
public:
Foo(int a, int b, int c, int d)
: m_a(a), m_b(b), m_c(c), m_d(d)
{ }
iterator begin() {
return iterator(*this, 0, &Foo::m_b, &Foo::m_d, &Foo::m_c, &Foo::m_a);
}
iterator end() {
return iterator(*this, 4, &Foo::m_b, &Foo::m_d, &Foo::m_c, &Foo::m_a);
}
private:
int m_a, m_b, m_c, m_d;
};
int main(int argc, char ** argv) {
Foo foo { 1, 2, 3, 4 };
for(auto & mem : foo) {
std::cout << mem.get() << std::endl;
mem.set(3);
}
for(auto & mem : foo) {
std::cout << mem.get() << std::endl;
}
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8aXRlcmF0b3I+CgpzdHJ1Y3QgRm9vOwoKdGVtcGxhdGU8dHlwZW5hbWUgVHlwZT4Kc3RydWN0IE1lbWJlclB0ckJhc2UgewogICAgdmlydHVhbCB+TWVtYmVyUHRyQmFzZSgpIHsgfQoKCXZpcnR1YWwgVHlwZSBnZXQoKSBjb25zdCA9IDA7Cgl2aXJ0dWFsIE1lbWJlclB0ckJhc2UgJiBzZXQoVHlwZSBjb25zdCAmKSA9IDA7Cn07Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBDbGFzcywgdHlwZW5hbWUgUmVhbFR5cGUsIHR5cGVuYW1lIENvbW1vblR5cGU+CnN0cnVjdCBNZW1iZXJQdHIgOiBNZW1iZXJQdHJCYXNlPENvbW1vblR5cGU+IHsKcHVibGljOgoJTWVtYmVyUHRyKENsYXNzICogb2JqZWN0LCBSZWFsVHlwZShDbGFzczo6Km1lbWJlcikpCgk6IG1fb2JqZWN0KG9iamVjdCksIG1fcHRyKG1lbWJlcikKCXsgfQoKCUNvbW1vblR5cGUgZ2V0KCkgY29uc3QgewoJCXJldHVybiBtX29iamVjdC0+Km1fcHRyOwoJfQoKCU1lbWJlclB0ciAmIHNldChDb21tb25UeXBlIGNvbnN0ICYgdmFsKSB7CgkJbV9vYmplY3QtPiptX3B0ciA9IHZhbDsKCQlyZXR1cm4gKnRoaXM7Cgl9CgoJTWVtYmVyUHRyICYgb3BlcmF0b3I9KFJlYWxUeXBlIGNvbnN0ICYgdmFsKSB7CgkJcmV0dXJuIHNldCh2YWwpOwoJfQoKCW9wZXJhdG9yIENvbW1vblR5cGUoKSBjb25zdCB7CgkJcmV0dXJuIGdldCgpOwoJfQpwcml2YXRlOgoJQ2xhc3MgKiBtX29iamVjdDsKCVJlYWxUeXBlIChDbGFzczo6Km1fcHRyKTsKfTsKCnRlbXBsYXRlPHR5cGVuYW1lIENsYXNzLCB0eXBlbmFtZS4uLiBUeXBlcz4Kc3RydWN0IE1lbWJlckl0ZXJhdG9yIHsKcHVibGljOgoJdXNpbmcgQ29tbW9uVHlwZSA9IHR5cGVuYW1lIHN0ZDo6Y29tbW9uX3R5cGU8VHlwZXMuLi4+Ojp0eXBlOwpwdWJsaWM6CglNZW1iZXJJdGVyYXRvcihDbGFzcyAmIG9iaiwgc3RkOjpzaXplX3QgaWR4LCBUeXBlcyhDbGFzczo6Ki4uLm1lbWJlcikpCgk6IG1fb2JqZWN0KG9iaiksIG1faW5kZXgoaWR4KSwgbV9tZW1iZXJzIHsgbmV3IE1lbWJlclB0cjxDbGFzcywgVHlwZXMsIENvbW1vblR5cGU+KCZvYmosIG1lbWJlcikuLi4gfQoJeyB9CgoJTWVtYmVyUHRyQmFzZTxDb21tb25UeXBlPiAmIG9wZXJhdG9yKigpIGNvbnN0IHsKCQlyZXR1cm4gKm1fbWVtYmVyc1ttX2luZGV4XTsKCX0KCglib29sIG9wZXJhdG9yPT0oTWVtYmVySXRlcmF0b3IgY29uc3QgJiBpdCkgY29uc3QgewoJCXJldHVybiAoJm1fb2JqZWN0ID09ICZpdC5tX29iamVjdCkgJiYgKG1faW5kZXggPT0gaXQubV9pbmRleCk7Cgl9CgoJYm9vbCBvcGVyYXRvciE9KE1lbWJlckl0ZXJhdG9yIGNvbnN0ICYgaXQpIGNvbnN0IHsKCQlyZXR1cm4gKCZtX29iamVjdCAhPSAmaXQubV9vYmplY3QpIHx8IChtX2luZGV4ICE9IGl0Lm1faW5kZXgpOwoJfQoKCU1lbWJlckl0ZXJhdG9yICYgb3BlcmF0b3IrKygpIHsKCQkrK21faW5kZXg7CgkJcmV0dXJuICp0aGlzOwoJfQpwcml2YXRlOgoJQ2xhc3MgJiBtX29iamVjdDsKCXN0ZDo6c2l6ZV90IG1faW5kZXg7CglNZW1iZXJQdHJCYXNlPENvbW1vblR5cGU+ICogbV9tZW1iZXJzW3NpemVvZi4uLihUeXBlcyldOwp9OwoKc3RydWN0IEZvbyB7CnB1YmxpYzoKCXVzaW5nIGl0ZXJhdG9yID0gTWVtYmVySXRlcmF0b3I8Rm9vLCBpbnQsIGludCwgaW50LCBpbnQ+OwpwdWJsaWM6CglGb28oaW50IGEsIGludCBiLCBpbnQgYywgaW50IGQpCgk6IG1fYShhKSwgbV9iKGIpLCBtX2MoYyksIG1fZChkKQoJeyB9CgoJaXRlcmF0b3IgYmVnaW4oKSB7CgkJcmV0dXJuIGl0ZXJhdG9yKCp0aGlzLCAwLCAmRm9vOjptX2IsICZGb286Om1fZCwgJkZvbzo6bV9jLCAmRm9vOjptX2EpOwoJfQoKCWl0ZXJhdG9yIGVuZCgpIHsKCQlyZXR1cm4gaXRlcmF0b3IoKnRoaXMsIDQsICZGb286Om1fYiwgJkZvbzo6bV9kLCAmRm9vOjptX2MsICZGb286Om1fYSk7Cgl9CnByaXZhdGU6CglpbnQgbV9hLCBtX2IsIG1fYywgbV9kOwp9OwoKaW50IG1haW4oaW50IGFyZ2MsIGNoYXIgKiogYXJndikgewoJRm9vIGZvbyB7IDEsIDIsIDMsIDQgfTsKCglmb3IoYXV0byAmIG1lbSA6IGZvbykgewoJCXN0ZDo6Y291dCA8PCBtZW0uZ2V0KCkgPDwgc3RkOjplbmRsOwoJCW1lbS5zZXQoMyk7Cgl9CgoJZm9yKGF1dG8gJiBtZW0gOiBmb28pIHsKCQlzdGQ6OmNvdXQgPDwgbWVtLmdldCgpIDw8IHN0ZDo6ZW5kbDsKCX0KfQ==