#include <iostream>
#include <functional>
 
template < typename T >
class my_ {
    T value;
    std::function<void(T const &)> notifier;
 public:
    template < typename F >
    my_( T const & init, F f )
    : value( init ), notifier( f ) {  }
    // for write
    T& operator=( T const & next ) {
        if( !std::equal_to<T>()(value, next) )
            notifier( next );
            
        return value = next;
    }
    // for read
    operator T const & () const
    { return value; }
}; 
 
struct Foo {
    Foo( int init )
    : value( init, 
             []( int const & next ) {
                 std::cout << "\tvalue changed to :" << next << std::endl; 
                 
             } )
    { }
    
    my_<int> value;  
};
 
int main() {
    
    Foo foo( 2 );
    // write
    int new_values[] = { 1, 1, 1, 2, 3, 3 };
    size_t const size = sizeof(new_values) / sizeof(*new_values);
    
    for( size_t i = 0; i != size; ++i ) {
        std::cout << "set in index: " << i << std::endl;
        foo.value = new_values[ i ];
    }
 
    // read
    std::cout << "final value: " << foo.value << std::endl;
}