Skip to content

Instantly share code, notes, and snippets.

@grahamboree
Last active August 29, 2015 14:14
Show Gist options
  • Save grahamboree/30718f902cf97449f83a to your computer and use it in GitHub Desktop.
Save grahamboree/30718f902cf97449f83a to your computer and use it in GitHub Desktop.
//
// main.cpp
// blackboard_test
//
// Created by Graham Pentheny on 1/27/15.
// Copyright (c) 2015 Graham Pentheny. All rights reserved.
//
#include <iostream>
#include <string>
#include <unordered_map>
#include <functional>
#include <memory>
using namespace std;
class Blackboard {
// This is just here to give a common type to all values in the map.
struct BBContainer {
virtual ~BBContainer() = default;
};
template<typename T>
struct BBEntry : public BBContainer {
virtual ~BBEntry() = default;
virtual T& GetValue() = 0;
};
template<typename T>
struct BBValue : public BBEntry<T> {
BBValue(const T& value) : m_value(value) {}
BBValue(T&& value) : m_value(std::move(value)) {}
virtual ~BBValue() = default;
virtual T& GetValue() override { return m_value; }
private:
T m_value;
};
template<typename T>
struct BBFunction : public BBEntry<T> {
BBFunction(function<T()> fun) :m_fun(fun) {}
virtual ~BBFunction() = default;
virtual T& GetValue() override {
m_lastEvalResult = m_fun();
return m_lastEvalResult;
}
private:
T m_lastEvalResult;
function<T()> m_fun;
};
unordered_map<string, unique_ptr<BBContainer>> m_blackboard;
public:
template<typename T>
void Add(string key, const T& value) {
m_blackboard[std::move(key)] = unique_ptr<BBValue<T>>(new BBValue<T>(value));
}
template<typename T>
void Add(string key, T&& value) {
m_blackboard[std::move(key)] = unique_ptr<BBValue<T>>(new BBValue<T>(std::move(value)));
}
template<typename T>
void AddFunc(string key, function<T()> fun) {
unique_ptr<BBFunction<T>> entry(new BBFunction<T>(fun));
m_blackboard[key] = std::move(entry);
}
void Remove(const string& key) {
m_blackboard.erase(key);
}
template<typename T>
T Get(const string& key) {
return static_cast<BBEntry<T>*>(m_blackboard[key].get())->GetValue();
}
};
// Example object...
struct Conversation {};
bool needsUpdate() { cout << " <<EVALING needsUpdate function>> "; return false; }
int main(int argc, const char * argv[]) {
// Add some stuff to the blackboard.
Blackboard bb;
bb.Add("life", 100);
bb.Add("convo", unique_ptr<Conversation>(new Conversation()));
// Explicit specialization required when adding function pointers or lambdas because of template type deduction rules...
// Maybe there's some tricky way around having to specify the type every time.
bb.AddFunc<bool>("has_target", [](){
cout << " <<EVALING has_target lambda>> ";
return true;
});
bb.AddFunc<bool>("need_update", needsUpdate);
cout << "Current health: " << bb.Get<int>("life") << "\n";
cout << "Has target: " << bb.Get<bool>("has_target") << "\n";
cout << "Conversation pointer: " << bb.Get<Conversation*>("convo") << "\n";
// Callers don't need to know if they're getting a constant value or function call result.
string key = "need_update";
cout << "Needs update (function): " << bb.Get<bool>(key) << "\n";
bb.Remove(key);
bb.Add(key, true);
cout << "Needs update (constant): " << bb.Get<bool>(key) << "\n";
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment