Skip to content

Instantly share code, notes, and snippets.

@xlc
Created October 24, 2014 05:01
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 xlc/7d926e4370cbd11dd760 to your computer and use it in GitHub Desktop.
Save xlc/7d926e4370cbd11dd760 to your computer and use it in GitHub Desktop.
#include <cassert>
#include <deque>
#include <functional>
#include <algorithm>
#include <memory>
template <class TArg, class TFriend = void>
class Event {
friend TFriend;
private:
std::deque<std::pair<std::function<void(TArg const &)>, void *>> _listeners;
protected:
void fire(TArg const & t) {
for (auto const & func : _listeners) {
func(t);
}
}
public:
template <class TFunc>
void subscript(TFunc && func, void *key = -1) {
_listeners.emplace_back(std::forward<TFunc>(func), key);
}
void unscbscript(void *key) {
_listeners.erase(
std::remove_if(_listeners.begin(), _listeners.end(), [=](auto const& p){ p.second == key; }),
_listeners.end());
}
};
template <class T>
class ReadonlyValue : virtual public Event<T> {
public:
virtual ~ReadonlyValue() {}
virtual T value() const = 0;
};
template <class T>
class Value : virtual public ReadonlyValue<T> {
public:
virtual ~Value() {}
virtual void value(T const & t) = 0;
virtual void value(T && t) { value(t); }
};
template <class T>
class ConcreteValue : virtual public Value<T> {
private:
std::shared_ptr<T> _val;
public:
ConcreteValue(T const & t) : _val(new T(t)) {}
ConcreteValue(T && t) : _val(new T(std::move(t))) {}
T value() const override {
return *_val;
}
void value(T const & t) {
*_val = t;
}
void value(T && t) {
*_val = std::move(t);
}
};
template <class T>
ConcreteValue<std::decay<T>> make_value(T && t) {
return {t};
}
template <class T, class TLambda>
class LambdaReadonlyValue : virtual public ReadonlyValue<T> {
private:
TLambda _lambda;
public:
T value() const override {
return _lambda();
}
};
int main(){
auto a = make_value(1);
auto b = a;
assert(a.value() == 1);
assert(b.value() == 1);
a.value(2);
assert(a.value() == 2);
assert(b.value() == 2);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment