Created
January 12, 2013 17:38
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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