public
Created

multi_function - multicast observer. Based on Generalizing Observer By Herb Sutter http://www.drdobbs.com/cpp/generalizing-observer/184403873

  • Download Gist
gistfile1.cpp
C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
// 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 );
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.