#include <iostream>
#include <functional>

template <typename T>
struct property {
    typedef std::function<T(T)> filter_function;
    typedef T value_type;

    property() { }

    property(value_type value)
        : m_value(value)
    { }

    property(value_type value, filter_function onGet)
        : m_value(value)
        , m_onGet(onGet)
    { }

    property(value_type value, filter_function onGet, filter_function onSet)
        : m_value(value)
        , m_onGet(onGet)
        , m_onSet(onSet)
    { }

    operator value_type() const {
        if (m_onGet) {
            return m_onGet(m_value);
        }
        return m_value;
    }

    property& operator=(value_type value) {
        if (m_onSet) {
            m_value = m_onSet(value);
        } else {
            m_value = value;
        }
        return *this;
    }

    value_type      m_value;
    bool            m_readOnly;
    filter_function m_onGet;
    filter_function m_onSet;
};


class FuckingClass {
public:
    property<std::string> fuckingProperty;

    FuckingClass()
    { 
        fuckingProperty = property<std::string>("hello", 
            std::bind(&FuckingClass::OnFuckingPropertyGet, this, std::placeholders::_1),
            std::bind(&FuckingClass::OnFuckingPropertySet, this, std::placeholders::_1)
        );
    }

    std::string OnFuckingPropertyGet(std::string s) {
        std::cout << "Getting fuckingProperty original value=" << s << std::endl;
        return "learn c++ dude";
    }

    std::string OnFuckingPropertySet(std::string s) {
        std::cout << "Setting fuckingProperty to value=" << s << std::endl;
        return s;
    }
};

int main(int argc, char **argv) {
    FuckingClass instance;
    instance.fuckingProperty = "world";
    std::string s = instance.fuckingProperty;
    std::cout << "s = " << s << std::endl;
    return 0;
}