#include <iostream>
template <typename T, typename V>
class Property
{
public:
typedef V (T::*getter_type)() const;
typedef void (T::*setter_type)(const V &value);
Property(T *self, getter_type getter, setter_type setter) : self_(self), getter_(getter), setter_(setter) {}
V get() const { return (self_->*getter_)(); }
Property &set(const V &v) { (self_->*setter_)(v); return *this; }
operator V() const { return get(); }
Property &operator=(const V &v) { return set(v); }
Property &operator+=(const V &v) { return set(get() += v); }
private:
T *self_;
getter_type getter_;
setter_type setter_;
};
struct Integer
{
int value_;
Integer(const int value) : value_(value) {}
operator int() const { return value_; }
Integer &operator =(const int value) { value_ = value; return *this; }
Integer &operator +=(const int value) { value_ += value; return *this; }
friend std::ostream &operator<<(std::ostream &os, const Integer &i) { os << i.value_; return os; }
};
class Hoge
{
public:
Hoge() : foo(this, &Hoge::get_foo, &Hoge::set_foo), foo_(0xdeadbeef) {}
Property<Hoge, Integer> foo;
Integer get_foo() const { return foo_; }
void set_foo(const Integer &v) { foo_ = v; }
private:
Integer foo_;
};
int main()
{
Hoge hoge;
(hoge.foo = 123) += 456;
std::cout << hoge.foo << std::endl;
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgoKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHR5cGVuYW1lIFY+CmNsYXNzIFByb3BlcnR5CnsKcHVibGljOgogIHR5cGVkZWYgViAoVDo6KmdldHRlcl90eXBlKSgpIGNvbnN0OwogIHR5cGVkZWYgdm9pZCAoVDo6KnNldHRlcl90eXBlKShjb25zdCBWICZ2YWx1ZSk7CiAgUHJvcGVydHkoVCAqc2VsZiwgZ2V0dGVyX3R5cGUgZ2V0dGVyLCBzZXR0ZXJfdHlwZSBzZXR0ZXIpIDogc2VsZl8oc2VsZiksIGdldHRlcl8oZ2V0dGVyKSwgc2V0dGVyXyhzZXR0ZXIpIHt9CiAgViBnZXQoKSBjb25zdCB7IHJldHVybiAoc2VsZl8tPipnZXR0ZXJfKSgpOyB9CiAgUHJvcGVydHkgJnNldChjb25zdCBWICZ2KSB7IChzZWxmXy0+KnNldHRlcl8pKHYpOyByZXR1cm4gKnRoaXM7IH0KICBvcGVyYXRvciBWKCkgY29uc3QgeyByZXR1cm4gZ2V0KCk7IH0KICBQcm9wZXJ0eSAmb3BlcmF0b3I9KGNvbnN0IFYgJnYpIHsgcmV0dXJuIHNldCh2KTsgfQogIFByb3BlcnR5ICZvcGVyYXRvcis9KGNvbnN0IFYgJnYpIHsgcmV0dXJuIHNldChnZXQoKSArPSB2KTsgfQpwcml2YXRlOgogIFQgKnNlbGZfOwogIGdldHRlcl90eXBlIGdldHRlcl87CiAgc2V0dGVyX3R5cGUgc2V0dGVyXzsKfTsKCnN0cnVjdCBJbnRlZ2VyCnsKICBpbnQgdmFsdWVfOwogIEludGVnZXIoY29uc3QgaW50IHZhbHVlKSA6IHZhbHVlXyh2YWx1ZSkge30KICBvcGVyYXRvciBpbnQoKSBjb25zdCB7IHJldHVybiB2YWx1ZV87IH0KICBJbnRlZ2VyICZvcGVyYXRvciA9KGNvbnN0IGludCB2YWx1ZSkgeyB2YWx1ZV8gPSB2YWx1ZTsgcmV0dXJuICp0aGlzOyB9CiAgSW50ZWdlciAmb3BlcmF0b3IgKz0oY29uc3QgaW50IHZhbHVlKSB7IHZhbHVlXyArPSB2YWx1ZTsgcmV0dXJuICp0aGlzOyB9CiAgZnJpZW5kIHN0ZDo6b3N0cmVhbSAmb3BlcmF0b3I8PChzdGQ6Om9zdHJlYW0gJm9zLCBjb25zdCBJbnRlZ2VyICZpKSB7IG9zIDw8IGkudmFsdWVfOyByZXR1cm4gb3M7IH0KfTsKCmNsYXNzIEhvZ2UKewpwdWJsaWM6CiAgSG9nZSgpIDogZm9vKHRoaXMsICZIb2dlOjpnZXRfZm9vLCAmSG9nZTo6c2V0X2ZvbyksIGZvb18oMHhkZWFkYmVlZikge30KICBQcm9wZXJ0eTxIb2dlLCBJbnRlZ2VyPiBmb287CiAgSW50ZWdlciBnZXRfZm9vKCkgY29uc3QgeyByZXR1cm4gZm9vXzsgfQogIHZvaWQgc2V0X2Zvbyhjb25zdCBJbnRlZ2VyICZ2KSB7IGZvb18gPSB2OyB9CnByaXZhdGU6CiAgSW50ZWdlciBmb29fOwp9OwoKaW50IG1haW4oKQp7CiAgSG9nZSBob2dlOwogIChob2dlLmZvbyA9IDEyMykgKz0gNDU2OwogIHN0ZDo6Y291dCA8PCBob2dlLmZvbyA8PCBzdGQ6OmVuZGw7CiAgcmV0dXJuIDA7Cn0K