#include <iostream>
#include <string>
template <typename T, typename V>
class Property
{
public:
typedef const 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); }
V operator()() const { return get(); }
friend std::ostream &operator<<(std::ostream &os, const Property &prop) { os << prop.get(); return os; }
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;
const std::string &get_str() const { 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+CmNsYXNzIFByb3BlcnR5CnsKcHVibGljOgogIHR5cGVkZWYgY29uc3QgViAmKFQ6OipnZXR0ZXJfdHlwZSkoKSBjb25zdDsKICB0eXBlZGVmIHZvaWQgKFQ6OipzZXR0ZXJfdHlwZSkoY29uc3QgViAmdmFsdWUpOwogIFByb3BlcnR5KFQgKnNlbGYsIGdldHRlcl90eXBlIGdldHRlciwgc2V0dGVyX3R5cGUgc2V0dGVyKSA6IHNlbGZfKHNlbGYpLCBnZXR0ZXJfKGdldHRlciksIHNldHRlcl8oc2V0dGVyKSB7fQogIFYgZ2V0KCkgY29uc3QgeyByZXR1cm4gKHNlbGZfLT4qZ2V0dGVyXykoKTsgfQogIFByb3BlcnR5ICZzZXQoY29uc3QgViAmdikgeyAoc2VsZl8tPipzZXR0ZXJfKSh2KTsgcmV0dXJuICp0aGlzOyB9CiAgb3BlcmF0b3IgVigpIGNvbnN0IHsgcmV0dXJuIGdldCgpOyB9CiAgUHJvcGVydHkgJm9wZXJhdG9yPShjb25zdCBWICZ2KSB7IHJldHVybiBzZXQodik7IH0KICBQcm9wZXJ0eSAmb3BlcmF0b3IrPShjb25zdCBWICZ2KSB7IHJldHVybiBzZXQoZ2V0KCkgKz0gdik7IH0KICBWIG9wZXJhdG9yKCkoKSBjb25zdCB7IHJldHVybiBnZXQoKTsgfQogIGZyaWVuZCBzdGQ6Om9zdHJlYW0gJm9wZXJhdG9yPDwoc3RkOjpvc3RyZWFtICZvcywgY29uc3QgUHJvcGVydHkgJnByb3ApIHsgb3MgPDwgcHJvcC5nZXQoKTsgcmV0dXJuIG9zOyB9CnByaXZhdGU6CiAgVCAqc2VsZl87CiAgZ2V0dGVyX3R5cGUgZ2V0dGVyXzsKICBzZXR0ZXJfdHlwZSBzZXR0ZXJfOwp9OwoKY2xhc3MgSG9nZQp7CnB1YmxpYzoKICBIb2dlKCkgOiBzdHIodGhpcywgJkhvZ2U6OmdldF9zdHIsICZIb2dlOjpzZXRfc3RyKSwgc3RyXygiSGVsbG8iKSB7fQogIFByb3BlcnR5PEhvZ2UsIHN0ZDo6c3RyaW5nPiBzdHI7CiAgY29uc3Qgc3RkOjpzdHJpbmcgJmdldF9zdHIoKSBjb25zdCB7IHJldHVybiBzdHJfOyB9CiAgdm9pZCBzZXRfc3RyKGNvbnN0IHN0ZDo6c3RyaW5nICZzKSB7IHN0cl8gPSBzOyB9CnByaXZhdGU6CiAgc3RkOjpzdHJpbmcgc3RyXzsKfTsKCmludCBtYWluKCkKewogIEhvZ2UgaG9nZTsKICBob2dlLnN0ciArPSAiLCBXb3JsZCEiOwogIHN0ZDo6Y291dCA8PCBob2dlLnN0cigpLmNfc3RyKCkgPDwgc3RkOjplbmRsOwogIHJldHVybiAwOwp9Cg==