#include <functional>
#include <vector>
#include <iostream>
#include <memory>
template < typename CB > struct event
{
std::vector< std::function<CB> > call_back ;
template < typename FN > event<CB>& operator+= ( FN fn )
{
call_back.emplace_back(fn) ;
return *this ;
}
};
struct test
{
const std::string& name() const { return name_ ; }
void name( const std::string& new_name )
{ name_ = new_name ; fire_name_changed() ; }
event< void( const test&, const std::string& ) > name_changed ;
template < typename FN, typename... ARGS > void subscribe( FN fn, ARGS&&... args )
{
using namespace std::placeholders ;
name_changed.call_back.emplace_back( std::bind( fn, args..., _1, _2 ) ) ;
}
private:
std::string name_ = "anonymous" ;
void fire_name_changed()
{ for( const auto& f : name_changed.call_back ) f( *this, name() ) ; }
};
void a_function( const test& sender, const std::string& value )
{
std::cout << "a_function: -\n name of object at "
<< std::addressof(sender) << " changed to: '" << value << "'\n\n" ;
}
void another_fun( const std::string& msg, const test& sender, const std::string& value )
{
std::cout << "another_fun: -\n msg: '" << msg
<< "'\n sender: " << std::addressof(sender)
<< "\n value: '" << value << "'\n\n" ;
}
int main()
{
test t ;
t.name_changed += []( const test& sender, const std::string& value )
{
std::cout << "lambda: -\n name of object at "
<< std::addressof(sender)
<< " changed to: '" << value << "'\n\n" ;
} ;
t.name_changed += a_function ;
t.subscribe( another_fun, "**** name of object is changed! ****" ) ;
struct recvr
{
void handle_it( const test& sender, const std::string& value ) const
{
std::cout << "recvr::handle_it -\n name of object at "
<< std::addressof(sender)
<< " changed to: '" << value << "'\n\n" ;
}
};
recvr r ;
t.subscribe( &recvr::handle_it, r ) ;
t.name( "Cambalinho" ) ; // change the name to test it
}