МануалМап заставит тебя вручную вызывать деструктор этого класса при анлоаде, поскольку тебе в любом случае придется делать объект этого класса глобальным, чтобы иметь возможность им пользоваться отовсюду. Что мешает тебе так же вручную вызвать деструктор для мапы? Делать этот же объект локальным нету абсолютно смысла, ибо жить он должен во всех потоках игры, где он может использоваться хотя бы гипотетически.
Деструктор std::optional вызывается тогда же, когда и все остальные деструкторы, потому что это обычный объект. Не понимаю, о чем ты говоришь.
Отправлять объект в динамическую память или использовать Singleton - не лучший вариант. В первом случае тебе все еще нужно будет самому контроллировать удаление объекта(Даже если он будет внутри std::unique_ptr, поскольку для него деструктор тоже не вызовется), а во втором случае у тебя и вовсе не будет контроля над тем, когда объект удаляется. Палка о двух концах
Так в данном случае я и принимаю критику. То, что я не проследил за инициализацией/выгрузкой имгуя - определенно мой косяк, доберусь до компа - поправлю(либо можете залить Pull Request на гитхаб). Да и сейчас я так же пытаюсь понять, чем в этом случае класс будет лучше пространства имен, но я попросту не вижу логики, так и так получится глобальный объект(максимум - с ограниченной областью видимости), который не будет вызывать свой деструктор во время выгрузке при инжекте через ManualMap
бро ты узко слишком мыслишь. суть глобала в общедоступости данных.
НО общедоступность данных можно реализовать не только через глобальный объект.
руками я нихуя никогда не делаю(если сам этого не хочу), у меня все всегда автоматом, будь то мануалмап или любой другой способ инжекта.
std::optional у тебя(например CTX::Config) это ГЛОБАЛЬНЫЙ ОБЪЕКТ. он при ммапе не будет разъебываться автоматически(как и твоя мапа и прочие глобалы. глобалы конструируются до main и деструктируются после main(точнее в CRT'шных точках входа и выхода которые до и после мейна идут)). при ммапе хуй тебе а не выход CRT.
Singleton - это ахуенная тема. это не какая-то конкретная имплементация. это шаблон, принцип, техника программирования(которая грубо говоря заключается в том что ты создаешь не более чем 1 шт объекта за всю жизнь). этот шаблон можно спокойно осуществить таким способом что у тебя будет ахуительнейший контроль и всё что нужно для счастья. у самого понятия "Singleton" нет никаких изъянов. изъяны есть у имплементаций. если все ахуенно сделать - это имба. вопрос лишь в воображении и твоих нуждах.
про "локальные объекты" - зависит от дизайна. твой дизайн с ними несовместим.
я же предпочитаю такой дизайн, что у меня все ресурсы лежат в моём "инит" треде, который просто держит ресурсы и ожидает деинжекта и после сигнала(ну или в случае исключения) раскручивает стек и разъебывает все ресурсы(= снимает все хуки хуюки и тд).
init:
{
try{
auto hooks = HookSomeShit();
await deinit;
}
catch ... //все дерьмо из try блока удаляется по RAII если вдруг исключение вылетит
}
в итоге у меня невъебически строгий контроль ресурсов - я АБСОЛЮТНО ВСЕ ресурсы(хуки консоли и тд) держу в стеке, в случае исключения или при выходе из чита автоматом все разъебывается засчёт stack unwinding'а. чисто всё локальное у меня. ни один ресурс не сможет убежать никуда. сдохну я = сдохнут все ресурсы. но при этом всё что надо еще и общедоступное(засчёт указателей которые указывают в мой стек).
Singleton состоит из хранилища(память под данные объекта), Create и Destroy.
в моей имплементации Singleton'ы имеют локальное хранилище(= хранятся в стеке "инит" треда. стек треда умирает вместе с тредом, а к тому моменту когда тред умрёт мой чит уже полностью будет мертв все хуки сняты и всё уже мертвое), и имеют контроллер(хуита которая при создании вызывает Create и при смерти вызывает Destroy. то есть RAII обертка на синглтон) и спокойно поддерживают исключения при конструкции с нормальным удалением созданных в процессе проваленной конструкции подресурсов(например пускай я создаю синглтон логгера - сначала создал консоль, потом допустим зафейлился фреопен - консоль освободится автоматом).
общедоступность я сделал просто через глобальный указатель(глобальная переменная)(который указывает на стек). кому нужен доступ к объекту - берут указатель(ну точнее референс) и работают с объектом. так же если кто-то захочет он может чекнуть жив ли синглтон(на случай если он был руками заранее убит например) чекнув указатель на ноль. кому нужны реальные гарантии живого синглтона - тот принимает референс на объект как аргумент(следовательно чтобы вызвать функцию мне сначала надо будет создать синглтон иначе я тупо не смогу вызвать функцию. вместо того чтобы мой инит сам бы брал логгер он просит логгер у того кто вызывает инит тем самым заставляя того кто вызывает инит создать логгер(ну этакое напоминание для меня чтобы я как программист не забыл что нужно создать синглтон)). кто уверен тот напрямую сам синглтон берет.
для синхронизации(чтобы при анхуке презента например не крашило) использую где надо двухступенчатый деинит(хукаю хуйню в мейн треде в таком месте где презент не вызывался бы параллельно(т.е. в месте где мейн тред держит какой-нибудь мьютекс который исключает возможность вызова презента параллельно), отправляю сигнал из этого мейн треда в свой инит тред(а мейн тред ждет ответного сигнала), в инит треде разъебываюсь и отдаю сигнал обратно в мейн тред который потом продолжает свою работу).
никогда руками нихуя не удаляю(если не надо заранее удалить), работает всё с любым способом инжекта.
синглтоны конструируются в самом начале инита в порядке важности(то есть к моменту какойто логики все синглтоны уже сконструированы).
синглтоны удаляются только при выходе из чита(и в ПРАВИЛЬНОМ ПОРЯДКЕ который я сам задал а не в рандомном), а к моменту выхода из чита вся логика(хуки и тд) уже 100% сдохла, и как следствие к мертвому синглтону никто не сможет уже обратиться.
наверняка есть какието дизайны которые еще пизже, я пока еще не придумал ничего мощнее.