Как обращаться со статическими членами и хранилищем класса шаблона в ситуациях, когда оставление статической очистки нежелательно

Я недавно вернулся к C++ после многих лет работы на C# и java, и мне нравится, куда C++ ушел в мое отсутствие (начиная с C++11, теперь я впитываю C++20!). Сила шаблонов действительно захватывает меня. Однако я быстро столкнулся с чем-то, с чем, кажется, невозможно справиться.

Я написал систему событий на основе шаблонов, которой очень доволен.

struct imgui_event_listener
{
    void onCreatedWindow(events::ImGui_CreatedWindow f)
    {

    }
}
dispatcher::connect(&listener, &imgui_event_listener::onCreatedWindow);
...
dispatcher::fire(events::ImGui_CreatedWindow{ window });

Мне это нравится, не требует параметров шаблона, может использовать произвольные структуры для событий. Однако есть одна большая загвоздка, и это почти бесконечные и совершенно непознаваемые потенциальные невидимые версии моей системы событий, использующие несколько unordered_maps, которые должны куда-то идти. В настоящее время они статичны внутри методов.

Такие вещи, как...

template <typename ListenerType, typename Type>
using FPtr = void(ListenerType::*)(Type);

template<typename ListenerType, typename Type>
using Tuple = eastl::tuple<ListenerType*, FPtr<ListenerType, Type>>;

template <typename ListenerType, typename Type>
using ListenerMap = eastl::unordered_map<uint32_t, Tuple<ListenerType, Type>>;

class EventSystem
{
    template<typename ListenerType, typename Type>
    ListenerMap<ListenerType, Type>& listenerMap()
    {
        static ListenerMap<ListenerType, Type> listenerMap;
        return listenerMap;
    }

}

Я относительный нуб в эти дни, так что простите, если что-то странное.

Это КАЖЕТСЯ слишком удобным и удовлетворительным, чтобы его можно было рекомендовать, я ожидал, что люди по какой-то причине будут перекрикиваться, но, похоже, именно так это по необходимости делается большую часть времени.

Но игровой движок, с которым я работаю, имеет диспетчер памяти и не использует и не рекомендует STL, имеет собственную замену, которая использует тот, который EA предлагает для игр с открытым исходным кодом, и имеет собственный распределитель, который следует использовать. для этого, чтобы он мог отслеживать память.

Это отслеживает все использование памяти и сообщает с исключением обо всех утечках, которые происходят во время удаления статических объектов.

К сожалению, несмотря на то, что контейнеры являются статическими, узлы этих unordered_maps выделяются из кучи, управляемой памятью. Ожидаемое использование будет состоять в том, чтобы очистить их при очистке, что происходит везде.

Теперь, я подозреваю, что на самом деле эти статические экземпляры карт будут автоматически обработаны после того, как диспетчер памяти уже пожаловался, однако на самом деле нет реального способа избежать его жалобы, даже если только в отладке, исключение при выходе и просмотр адресов памяти, о которых сообщается поскольку утечки раздражают, и мне становится стыдно, когда это происходит! Это также может скрыть реальные проблемы. Я уверен, что смогу перебрать нормальные карты STL с аллокациями, но я действительно хочу следовать по пути, проложенному разработчиками движка, и избежать головной боли в будущем. Так что это больше об удобстве и тщеславии, чем о чем-либо еще, но мне нужен способ обойти это, не жертвуя элегантностью использования моей системы событий.

Это привело меня в мир метапрограммирования шаблонов, чтобы попытаться сопоставить все эти параметры шаблона в какой-то мегакортеж по мере формирования соединений событий и экземпляров шаблона, созданных во время компиляции, и изучить каждый мыслимый шаблон, где я каким-то образом иметь возможность раскрутить все экземпляры шаблонов, которые я создал, чтобы получить их заранее, и иметь возможность вручную очистить, но кажется, что метапрограммирование шаблонов требует новых «имен переменных» для каждой инструкции в виде typedefs или с использованием средств, которые я могу не делайте этого итеративно из того, что я вижу, но, честно говоря, область настолько сложна и легка на соответствующих примерах, что я не знаю, упустил ли я что-нибудь.

Я пытался думать о том, где еще их можно было бы хранить, но я просто не могу понять, как это могло бы быть по-другому.

Я также мог бы просто вручную вести список всех своих событий, но тогда я потерял бы одну из его более крутых и гибких функций.

ИЛИ где-то еще я могу хранить их, где я смогу получить к ним доступ. Это похоже на ситуацию уловки 22, когда само их существование требует, чтобы они находились в какой-то недоступной параллельной вселенной.

Так что да, я знаю, что есть способы решить эту проблему, не обращаясь за помощью, но все они либо приносят в жертву функцию системы, либо потенциально вызывают проблемы в будущем. Не уверен, что я когда-либо задавал здесь вопрос, но это действительно поставило меня в тупик, и я не могу найти подобную проблему у кого-то другого, большинство из них с удовольствием используют стандартную библиотеку, не имеют диспетчера памяти и помещают статические экземпляры в функции это супер удовлетворительно простой способ сделать это.

Спасибо за ваше время! Простите, если немного бессвязно, но я чувствовал, что мне нужно предоставить контекст. Я знаю, что на самом деле не так много кода, но я надеюсь, что вы поняли мою точку зрения!

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Возможно, что-то в этом роде:

std::vector<std::function<void()>> cleanup_registry;

class EventSystem
{
    template<typename ListenerType, typename Type>
    ListenerMap<ListenerType, Type>& listenerMap()
    {
        static ListenerMap<ListenerType, Type> listenerMap;
        static int dummy = (
           cleanup_registry.push_back([&]() { listenerMap.clear(); }),
           0);
        return listenerMap;
    }
};

void cleanup() {
  for (auto& cleaner : cleanup_registry) {
    cleaner();
  }
  std::vector<std::function<void()>>{}.swap(cleanup_registry);
}

Позвоните cleanup() прямо перед тем, как ваш игровой движок отключится.


Вы можете использовать аналогичные методы стирания типов, чтобы исключить ListenerType из своих карт, имея только одну карту для каждого типа события. Что-то вроде

template <typename Event>
using ListenerMap = eastl::unordered_map<uint32_t, std::function<void(Event)>>;

Затем dispatcher::connect (где доступен фактический тип слушателя) создаст лямбду обратного вызова для размещения на карте.

Черт возьми, ты красивый умный человек!

Seb 101 18.02.2023 16:52

Это настолько элегантно и легко реализовать, что я три дня бился головой о стену, удивительно видеть, как это изложено таким простым способом. еще один инструмент в моем наборе инструментов, спасибо!

Seb 101 18.02.2023 16:58

Другие вопросы по теме

Похожие вопросы