Skip to content

Instantly share code, notes, and snippets.

@foobit
Created January 12, 2013 17:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save foobit/4519483 to your computer and use it in GitHub Desktop.
Save foobit/4519483 to your computer and use it in GitHub Desktop.
multi_function - multicast observer. Based on Generalizing Observer By Herb Sutter http://www.drdobbs.com/cpp/generalizing-observer/184403873
// Dr. Dobb's
// Generalizing Observer By Herb Sutter
// http://www.drdobbs.com/cpp/generalizing-observer/184403873
//
#pragma once
#include <list>
#include <functional>
template<typename F>
class multi_function : public std::function<F>
{
public:
typedef std::list<typename std::function<F>::result_type> result_type;
explicit multi_function() { }
// the implicitly generated copy constructor,
// copy assignment, and destructor are fine
template<typename F2> multi_function( std::function<F2> f ) { l_.push_back( f ); }
// if you have an implementation of function that supports
// equality comparison, uncomment the calls to remove
void add( std::function<F> f ) { /* l_.remove( f ); */ l_.push_back( f ); }
void remove( std::function<F> f ) { /* l_.remove( f ); */ }
void operator+=( std::function<F> f ) { add( f ); }
void operator-=( std::function<F> f ) { remove( f ); }
void swap( multi_function& other ) { l_.swap( other.l_ ); }
void clear() { l_.clear(); }
bool empty() const { return l_.empty(); }
operator bool() const { return l_.empty(); }
void operator()() const
{
for (auto i = l_.cbegin(); i != l_.cend(); ++i )
(*i)();
}
template<typename T1>
void operator()( T1 t1 ) const
{
for (auto i = l_.cbegin(); i != l_.cend(); ++i )
(*i)( t1 );
}
template<typename T1, typename T2>
void operator()( T1 t1, T2 t2 ) const
{
for (auto i = l_.cbegin(); i != l_.cend(); ++i )
(*i)( t1, t2 );
}
template<typename T1, typename T2, typename T3>
void operator()( T1 t1, T2 t2, T3 t3 ) const
{
for (auto i = l_.cbegin(); i != l_.cend(); ++i )
(*i)( t1, t2, t3 );
}
template<typename T1, typename T2, typename T3, typename T4>
void operator()( T1 t1, T2 t2, T3 t3, T4 t4 ) const
{
for (auto i = l_.cbegin(); i != l_.cend(); ++i )
(*i)( t1, t2, t3, t4 );
}
// etc.
private:
std::list<std::function<F> > l_;
};
template<typename MF1, typename MF2>
void swap( multi_function<MF1>& mf1, multi_function<MF2>& mf2 )
{
mf1.swap( mf2 );
}
template<typename MF1, typename MF2>
bool operator==( const multi_function<MF1>& mf1, const multi_function<MF2>& mf2 )
{
// if function doesn't provide comparisons, this is unimplementable
// if function provides op==, this is inefficient: O(N^2) operation
// if function provides op<, this is efficient: can keep lists sorted, or use a set
// for now, install a placeholder:
return false;
}
template<typename MF1, typename MF2>
bool operator!=( const multi_function<MF1>& mf1, const multi_function<MF2>& mf2 )
{
return !( mf1 == mf2 );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment