#include <iostream>
#include <string>
template <typename T, typename V>
class Property
{
public:
typedef V *(T::*getter_type)();
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); }
V *operator ->() const { return (self_->*getter_)(); }
private:
T *self_;
getter_type getter_;
setter_type setter_;
};
class Hoge
{
public:
Hoge() : str(this, &Hoge::get_str, &Hoge::set_str), str_("Hello") {}
Property<Hoge, std::string> str;
std::string *get_str() { return &str_; }
void set_str(const std::string &s) { str_ = s; }
private:
std::string str_;
};
int main()
{
Hoge hoge;
hoge.str += ", World!";
std::cout << hoge.str->c_str() << std::endl;
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8c3RyaW5nPgoKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHR5cGVuYW1lIFY+CmNsYXNzIFByb3BlcnR5CnsKcHVibGljOgogIHR5cGVkZWYgViAqKFQ6OipnZXR0ZXJfdHlwZSkoKTsKICB0eXBlZGVmIHZvaWQgKFQ6OipzZXR0ZXJfdHlwZSkoY29uc3QgViAmdmFsdWUpOwogIFByb3BlcnR5KFQgKnNlbGYsIGdldHRlcl90eXBlIGdldHRlciwgc2V0dGVyX3R5cGUgc2V0dGVyKSA6IHNlbGZfKHNlbGYpLCBnZXR0ZXJfKGdldHRlciksIHNldHRlcl8oc2V0dGVyKSB7fQogIFYgZ2V0KCkgY29uc3QgeyByZXR1cm4gKihzZWxmXy0+KmdldHRlcl8pKCk7IH0KICBQcm9wZXJ0eSAmc2V0KGNvbnN0IFYgJnYpIHsgKHNlbGZfLT4qc2V0dGVyXykodik7IHJldHVybiAqdGhpczsgfQogIG9wZXJhdG9yIFYoKSBjb25zdCB7IHJldHVybiBnZXQoKTsgfQogIFByb3BlcnR5ICZvcGVyYXRvcj0oY29uc3QgViAmdikgeyByZXR1cm4gc2V0KHYpOyB9CiAgUHJvcGVydHkgJm9wZXJhdG9yKz0oY29uc3QgViAmdikgeyByZXR1cm4gc2V0KGdldCgpICs9IHYpOyB9CiAgViAqb3BlcmF0b3IgLT4oKSBjb25zdCB7IHJldHVybiAoc2VsZl8tPipnZXR0ZXJfKSgpOyB9CnByaXZhdGU6CiAgVCAqc2VsZl87CiAgZ2V0dGVyX3R5cGUgZ2V0dGVyXzsKICBzZXR0ZXJfdHlwZSBzZXR0ZXJfOwp9OwoKY2xhc3MgSG9nZQp7CnB1YmxpYzoKICBIb2dlKCkgOiBzdHIodGhpcywgJkhvZ2U6OmdldF9zdHIsICZIb2dlOjpzZXRfc3RyKSwgc3RyXygiSGVsbG8iKSB7fQogIFByb3BlcnR5PEhvZ2UsIHN0ZDo6c3RyaW5nPiBzdHI7CiAgc3RkOjpzdHJpbmcgKmdldF9zdHIoKSB7IHJldHVybiAmc3RyXzsgfQogIHZvaWQgc2V0X3N0cihjb25zdCBzdGQ6OnN0cmluZyAmcykgeyBzdHJfID0gczsgfQpwcml2YXRlOgogIHN0ZDo6c3RyaW5nIHN0cl87Cn07CgppbnQgbWFpbigpCnsKICBIb2dlIGhvZ2U7CiAgaG9nZS5zdHIgKz0gIiwgV29ybGQhIjsKICBzdGQ6OmNvdXQgPDwgaG9nZS5zdHItPmNfc3RyKCkgPDwgc3RkOjplbmRsOwogIHJldHVybiAwOwp9Cg==