#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;
}
