Forums before death by AOL, social media and spammers... "We can't have nice things"
|    comp.lang.c++.moderated    |    Moderated discussion of C++ superhackery    |    33,346 messages    |
[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]
|    Message 32,742 of 33,346    |
|    fmatthew5876 to Balog Pal    |
|    Re: Singletons    |
|    16 Dec 12 19:40:41    |
      From: fmatthew5876@googlemail.com              On Sunday, December 16, 2012 10:27:05 AM UTC-5, Balog Pal wrote:       > On 12/14/2012 1:21 AM, Öö Tiib wrote:       >       > > First ... about your idea in general. Making unit tests is difficult       > > when singular state on what your unit depends is behind free functions       > > and you use some mocking framework that does not help turning free       > > functions into mock versions.       >       > Can you give a C++ example for this? IME you just use its regular       > header, then the linker obviously will miss the function body, and you       > provide an implementation.       >              I actually agree more the first poster here. Singletons do make creating       mock versions trivially easy if you use virtual functions.              In all other cases, yes you can just include the headers and provide       your own mock implementations but this may not be so straightforward. If       your code base is a library, you might be just linking small unit test       executables to it to do various tests. In this case without some       implementation specific compiler/linker hackery its not so easy to       replace the functions with mock versions.              > And you can help with the preprocessor too defining a macro for the       > function name that hijacks it. (the singleton accessor function shall       > have a unique name, right?)              Using the preprocessor here seems like a non-starter to me, especially       if you have nested namespaces or indirect access. One part may want to       access name::foo(), the other just foo(). The preprocessor also does not       help if you if you are testing code already compiled within your library.       In that case you really do want virtual or some kind of pimp idiom so       that the already compiled code just unknowingly calls your mock versions.                     It looks like using a gate keeper such as getInstance() is very helpful       for some things:              If you want lazy initialization, using getInstance() is a great way to       do this. Nobody wants to write an initialization check to every single       method or trust that other developers will not forget to do so.              If you need thread safety, getInstance() could also return a class type       that not only provides singleton access but also locks a mutex. Once your       "singleton handle" is destroyed it can automatically free the lock in       the destructor.              And of course, enforcing the one-instance rule at compile time, which is what       this whole thing was developed for in the first place.              In my case I don't care at all about lazy initialization or thread safety. For       a game engine that is not going to be layered into other libraries, requiring       the user to call init() and shutdown() in order in the main function is not too       much to ask. Explicit initialization also means that the client can       pass parameters to the initialization routine, which is my case happens       to be configuration data parsed from config files and command line options.              Finally, a game engine with several sub systems such as graphics, physics,       audio, and ai, there is often a specific order things need to brought up and       torn down. Using lazy initialization makes this order hard to figure out and       easy to break.              Seeing as my requirements don't require a gate keeper, I'd rather simplify and       just have a global object I can call methods on or a set of free functions.              The disadvantage of a static global object is that now the data members and       private methods of the object have to be exposed in the header file. Every time       they change (which can be often, especially for private methods) everyone       including this header (which will be a lot of files, considering its a global)       has to recompile.              There are several options I could come up with to fixing the       recompilation issue:       1) Hide the data behind free functions       2) Use a global static object with only methods and no data, it can simply call       the methods of the real global singleton hidden in the implementation.       3) Make your exposed singleton a pure virtual base class a reference       or pointer.              3 is interesting because you can actually provide the one instance guarantee       at compile time by making the constructor and destructor protected. An exposed       global reference can easily be seated to a static version of the real subclass.       The cost of course being the overhead of virtual functions.                     --        [ See http://www.gotw.ca/resources/clcm.htm for info about ]        [ comp.lang.c++.moderated. First time posters: Do this! ]              --- SoupGate-Win32 v1.05        * Origin: you cannot sedate... all the things you hate (1:229/2)    |
[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]
(c) 1994, bbs@darkrealms.ca