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