Last active
August 29, 2015 14:14
-
-
Save grahamboree/30718f902cf97449f83a to your computer and use it in GitHub Desktop.
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
// | |
// 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