I made it using this answer this answer, posted on Stack Overflow, as reference. A lot of problems arose when I switched C function pointers to std::function
due to the lack of the equality operator on it, so I ended up implementing a internal class to hold a pointer to the function and make it comparable.
I made it using this answer, posted on Stack Overflow, as reference. A lot of problems arose when I switched C function pointers to std::function
due to the lack of the equality operator on it, so I ended up implementing a internal class to hold a pointer to the function and make it comparable.
I made it using this answer, posted on Stack Overflow, as reference. A lot of problems arose when I switched C function pointers to std::function
due to the lack of the equality operator on it, so I ended up implementing a internal class to hold a pointer to the function and make it comparable.
C++ generic Generic event class - am I over-complicating it?
I made it using this answer, posted on stackoverflowStack Overflow, as reference. A lot of problems arose when I switched C function pointers to std::functionstd::function
due to the lack of the equality operator on it, so I ended up implementing a internal class to hold a pointer to the function and make it comparable.
C++ generic event class - am I over-complicating it?
I made it using this answer, posted on stackoverflow, as reference. A lot of problems arose when I switched C function pointers to std::function due to the lack of the equality operator on it, so I ended up implementing a internal class to hold a pointer to the function and make it comparable.
Generic event class - am I over-complicating it?
I made it using this answer, posted on Stack Overflow, as reference. A lot of problems arose when I switched C function pointers to std::function
due to the lack of the equality operator on it, so I ended up implementing a internal class to hold a pointer to the function and make it comparable.
C++ generic event class - am I over-complicating it?
I'd like some advice about any better or cleaner way to implement this class, if there's any.
I made it using this answer, posted on stackoverflow, as reference. A lot of problems arose when I switched C function pointers to std::function due to the lack of the equality operator on it, so I ended up implementing a internal class to hold a pointer to the function and make it comparable.
#include <list> // std::list
#include <algorithm> // std::find
#include <functional> // std::function
#include <memory> // std::auto_ptr
template<typename FuncTemplate>
class Event
{
public: // Type declarations
class Delegate;
public:
Event() = default;
~Event() = default;
Event& operator+=(const Delegate& func)
{
events.push_back(func);
return *this;
}
/**
* Removes the first occurence of the given delegate from the call queue.
*/
Event& operator-=(const Delegate& func)
{
auto index = std::find(events.begin(), events.end(), func);
if(index != events.end() )
{
events.erase(index);
}
return *this;
}
/**
* Fires this event.
*
* @param args Arguments to be passed to the called functions. Must have the exact same
* number of arguments as the given event template.
*/
template<typename... Args>
void operator()(Args... args)
{
for (typename std::list<Delegate>::iterator i = events.begin(); i != events.end(); ++i)
{
(*i)(args...);
}
}
private: // Private variables
std::list<Delegate> events;
public:
class Delegate
{
private: // Type declarations
typedef std::function<FuncTemplate> Func;
public:
Delegate (const Func& func) : functionPtr(new Func(func))
{
/* NOP */
}
inline bool operator== (const Delegate& other) const
{
return (functionPtr.get() == other.functionPtr.get() );
}
template<typename... Args>
void operator()(Args... args)
{
(*functionPtr)(args...);
}
private:
std::shared_ptr<Func> functionPtr;
};
};
This is the code I used to test it:
void prints(const std::string& e)
{
std::cout << "From prints: " << e << std::endl;
}
int main(int argc, char *argv[])
{
Event<void(const std::string&)> messageReceived;
auto printLambda = [](const std::string& e) -> void
{
std::cout << "From print lambda: " << e << std::endl;
};
Event<void(const std::string&)>::Delegate printDelegate1(printLambda); // Testing lambda
Event<void(const std::string&)>::Delegate printDelegate2(prints); // Testing standard functions
Event<void(const std::string&)>::Delegate printDelegate3(printLambda); // Testing lamda on another delegate instance
Event<void(const std::string&)>::Delegate printDelegate4(printDelegate1); // Testing cloning constructor
Event<void(const std::string&)>::Delegate printDelegate5 = printDelegate1; // Testing assignation
std::cout << "Is Delegate 1 = Delegate 1? " << (printDelegate1 == printDelegate1) << std::endl;
std::cout << "Is Delegate 1 = Delegate 2? " << (printDelegate1 == printDelegate2) << std::endl;
std::cout << "Is Delegate 1 = Delegate 3? " << (printDelegate1 == printDelegate3) << std::endl;
std::cout << "Is Delegate 1 = Delegate 4? " << (printDelegate1 == printDelegate4) << std::endl;
std::cout << "Is Delegate 1 = Delegate 5? " << (printDelegate1 == printDelegate5) << std::endl;
std::cout << std::endl << std::endl;
messageReceived += printDelegate1;
messageReceived += printDelegate2;
messageReceived += printDelegate3;
messageReceived += printDelegate4;
messageReceived += printDelegate5;
messageReceived("This should be printed five times");
std::cout << std::endl;
messageReceived -= printDelegate1;
messageReceived -= printDelegate2;
messageReceived -= printDelegate3;
messageReceived("This should be printed two times");
std::cout << std::endl;
messageReceived -= printDelegate4;
messageReceived -= printDelegate5;
messageReceived("Whoops! Something is wrong");
return 0;
}