Skip to content

Instantly share code, notes, and snippets.

@facontidavide
Last active July 16, 2020 12:46
Show Gist options
  • Save facontidavide/bc18c3bc5d2d595a4c823cfe16f3eb68 to your computer and use it in GitHub Desktop.
Save facontidavide/bc18c3bc5d2d595a4c823cfe16f3eb68 to your computer and use it in GitHub Desktop.
Super Simple Signal Slot implementation in C++ 11
#include <stdio.h>
#include <memory>
#include <functional>
#include <list>
/**
* Super simple Signal/Slop implementation, AKA "Observable pattern".
* The subscriber is active until it goes out of scope or Subscriber::reset() is called.
*/
template <typename... CallableArgs>
class Signal{
public:
using CallableFuntion = std::function<void(CallableArgs...)>;
using Subscriber = std::shared_ptr<CallableFuntion>;
void operator()(CallableArgs... args)
{
auto it = subscribers_.begin();
while (it != subscribers_.end() )
{
if( auto sub = it->lock() )
{
(*sub)(args...);
it++;
}
else{
auto prev_it = it++;
subscribers_.erase(prev_it);
}
}
}
Subscriber subscribe(CallableFuntion func)
{
Subscriber sub = std::make_shared<CallableFuntion>(std::move(func));
subscribers_.emplace_back(sub);
return sub;
}
private:
std::list<std::weak_ptr<CallableFuntion>> subscribers_;
};
int main()
{
Signal<int,int> signaler;
{
auto sub1 = signaler.subscribe([](int a, int b){ printf("pair: %d %d\n", a,b); });
{
auto sub2 = signaler.subscribe([](int a, int b){ printf("add: %d\n", a+b); });
signaler(3,7);
// output (sub1 and sub2):
//
// > pair: 3 7
// > add: 10
}
signaler(4,1);
// output (only sub1):
//
// > pair: 4 1
}
signaler(2,2);
// NO output.
auto sub3 = signaler.subscribe([](int a, int b){ printf("mult: %d\n", a*b); });
signaler(3,5);
// output (sub3):
//
// > mult: 15
sub3.reset();
signaler(4,4);
// NO output.
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment