Replace the `hookset` typedef with a full-blown class type. NFC.

This restricts the "API surface area" of `hookset` to just these three
accessor methods; there's no longer any way to break into a hookset and
iterate it manually, or erase elements from a hookset, or ask for its
size, or anything else that you could have done given the raw `std::map *`.
This commit is contained in:
Arthur O'Dwyer 2020-04-11 20:44:31 -04:00
parent 961a8919c6
commit d1458b3ee5
1 changed files with 41 additions and 18 deletions

59
hyper.h
View File

@ -407,9 +407,41 @@ struct movedir {
// shmup
template<class T> class hookset_impl : public map<int, function<T>> {};
template<class T> using hookset = hookset_impl<T> *;
using purehookset = hookset_impl<void()> *;
template<class T>
class hookset {
std::map<int, std::function<T>> *map_ = nullptr;
public:
template<class U>
int add(int prio, U&& hook) {
if (map_ == nullptr) map_ = new std::map<int, std::function<T>>();
while (map_->count(prio)) {
prio++;
}
map_->emplace(prio, static_cast<U&&>(hook));
return 0;
}
template<class... U>
void callhooks(U&&... args) const {
if (map_ == nullptr) return;
for (const auto& p : *map_) {
p.second(static_cast<U&&>(args)...);
}
}
template<class V, class... U>
V callhandlers(V zero, U&&... args) const {
if (map_ == nullptr) return zero;
for (const auto& p : *map_) {
auto z = p.second(static_cast<U&&>(args)...);
if (z != zero) return z;
}
return zero;
}
};
using purehookset = hookset<void()>;
static const int NOHINT = -1;
@ -634,25 +666,16 @@ color_t darkena(color_t c, int lev, int a);
static const int DISTANCE_UNKNOWN = 127;
template<class T, class U> int addHook(hookset<T>& m, int prio, const U& hook) {
if(!m) m = new hookset_impl<T> ();
while(m->count(prio)) {
prio++;
}
(*m)[prio] = hook;
return 0;
template<class T, class U> int addHook(hookset<T>& m, int prio, U&& hook) {
return m.add(prio, static_cast<U&&>(hook));
}
template<class T, class... U> void callhooks(hookset<T> h, U&&... args) {
if(h) for(auto& p: *h) p.second(std::forward<U>(args)...);
template<class T, class... U> void callhooks(const hookset<T>& h, U&&... args) {
return h.callhooks(static_cast<U&&>(args)...);
}
template<class T, class V, class... U> V callhandlers(V zero, hookset<T> h, U&&... args) {
if(h) for(auto& p: *h) {
auto z = p.second(std::forward<U>(args)...);
if(z != zero) return z;
}
return zero;
template<class T, class V, class... U> V callhandlers(V zero, const hookset<T>& h, U&&... args) {
return h.callhandlers(zero, static_cast<U&&>(args)...);
}
string XLAT(string);