4 ms·
Tbh, I never understood the point of singletons in C++ versus just having a namespace with functions in it, e.g. instead of auto& s = DisplayManager::Ins
by flohofwoe 8mo ago
Tbh, I never understood the point of singletons in C++ versus just having a namespace with functions in it, e.g. instead of
auto& s = DisplayManager::Instance();
s.SetResolution(Resolution::r640x480);
...just this:
Display::SetResolution(Resolution::r640x480);
...since it's a singleton, the state only exists once anyway so there's no point in wrapping it in an object.
E.g. what's the point of globally visible singletons except "everything is an object" cargo-culting?
- adzm 8mo agoA static class member function would be the same in your example. If you don't have any state to maintain, then that's fine. The reason people use singletons is to manage that state; it's easier to handle it all in a class instance. If you end up having to manage it in a function using globals or static instances somewhere you get the same issues. Also often the object exposed as a Singleton is not the only use of that object.
- not_the_fda 8mo agoIts brain damage from people coming from Java. Just put your state in an anonymous namespace in the implementation file.
- deleted 8mo ago[deleted]
- TuxSH 8mo agoIn your case SetResolution could be a static method calling a private instance-method SetResolutionImpln, for example, similar to what other people said. > what's the point of globally visible singletons except "everything is an object" cargo-culting? Having the singleton be an object becomes interesting when: 1) it contains attributes that themselves have non-trivial constructors and/or destructors. Order of initialization and destruction is guaranteed (init is in forward order of declaration, destruction in reverse order) 2) more rarely, inheritance (code reuse) In the case of 1), you can just opt to construct the singleton on a sufficiently-aligned byte buffer in-place with `std::construct_at`. This gets rid of static-init order fiasco, __cxa bloat (if applicable), atexit bloat, and you can chose to just not call `std::destroy_at` if you don't need to. In these two scenarios it's a lot more efficient to group many related objects into a bigger object.