AI prompt words
using eca_cond = bool(*)(...);
using eca_action = void(*)(...);
class eca_info
{
public:
eca_cond m_cond;
eca_action m_action;
void* m_handler_owner;
};
using eca_infos = std::vector<eca_info>;
void listen(const std::string& key, eca_action action, void* handler_owner = nullptr);
void listen(const std::string& key, eca_cond cond, eca_action action, void* handler_owner = nullptr);
const eca_infos& get_infos(const std::string& key);
template<typename... Args>
inline void trigger(const std::string& key, Args ...args)
{
auto infos get_infos(key);
for (auto& info : infos)
{
if (info.m_cond && !info.m_cond(...args))
{
continue;
}
if (info.handler_owner)
{
// Call object method
(info.handler_owner)->info.m_action()...args);
}
else
{
// Call global functions
info.m_action(...args);
}
}
}
Complete the above functions
Modified ECA system:
#pragma once
#include <cstdint>
#include <string>
#include <vector>
#include <unordered_map>
// Define the types of conditions and actions
using eca_cond = bool(*)(...);
using eca_action = void(*)(...);
// Event information structure, including the owner of the condition, action and event handler
class eca_info {
public:
eca_cond m_cond; // Conditional function
eca_action m_action; // Action function
void* m_handler_owner; // owner of event handler, used for object method calls
};
// Use vectors to store event information to manage multiple events
using eca_infos = std::vector<eca_info>;
// Simulated global storage, used to save the event information list corresponding to different keys
using eca_map = std::unordered_map<std::string, eca_infos>;
inline eca_map& get_eca_map()
{
static eca_map eca_map_;
return eca_map_;
}
// Listen to events and register actions
void listen(const std::string& key, eca_action action, void* handler_owner = nullptr)
{
get_eca_map()[key].push_back({nullptr, action, handler_owner});
}
// Listen to events, registration conditions and actions
void listen(const std::string& key, eca_cond cond, eca_action action, void* handler_owner = nullptr)
{
get_eca_map()[key].push_back({cond, action, handler_owner});
}
// Get the list of event information corresponding to a specific event key
const eca_infos& get_infos(const std::string& key)
{
static const eca_infos empty; // empty list is used for cases not found
auto map = get_eca_map();
return (key) ? map[key] : empty;
}
// Trigger event
template<typename... Args>
inline void trigger(const std::string& key, Args... args) {
auto& infos = get_infos(key); // Get all information about the corresponding event
for (auto& info : infos) {
// If a condition function exists and the condition is not satisfied, skip this action
if (info.m_cond && !info.m_cond(args...)) {
continue;
}
// Determine whether there is an owner of the event handler (object method call)
if (info.m_handler_owner)
{
// Call the object method, assuming that the action function is a member function of the object
// Note: tweaks may be required here to correctly call member functions
(static_cast<void(*)(void*, Args...)>(info.m_action))(info.m_handler_owner, args...);
}
else
{
// Call global or static functions
info.m_action(args...);
}
}
}