The Reset trick
My last month's post, Singleton done right in C++, has triggered plenty of comments. I expected a few, but not that much. So thank you for keeping the conversation going.
As I said in my previous post, this is not to advertise singletons at all. It is just if you use them, at least do so correctly.
I picked one comment that I received multiple times that questioned why I was making the copy- and move-operations private and defaulted them at the same time. Here is the original code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | |
Please note, in the spirit of the blog post's name, Singleton done right in C++, I now change the code to =delete and making the functions public. Thinking more of best by default.
There is a reason
Back to the question, why did I make these functions private and =default. There is a reason. Consider a different example of a ConfigManager where I use the private and default pattern:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | |
Once again, a singleton. With three non-static member functions. Two of them are for accessing configuration values stored in the manager object. The third one, Reset, in C, well it is supposed to reset the object.
This reset is achieved by creating a new ConfigManager object B and moving it into this C. Whether you use move or do a swap depends on what you like to model. In a throwing world where a failed move triggers a program termination, the code presented ensures that the reset always succeeds, or the program terminates. By using a swap you leave the door open for an exception situation that needs to be handled. But you can handle it the way it is appropriate.
Regardless of whether you move or swap for this pattern, the copy, or move operations must be accessible by the class internally. Which is the reason I defaulted these and put them into the private access part.
This pattern allows you to leave the destructor of the class as it is. No tampering required at all. You can always be certain that after Reset your object is in a default constructed state without having to do things manually, twice, or by risking that the destructor does other things than the Reset function.
I hope this clears up why I used my approach. But I take the feedback that using =delete by default is the better choice. Sorry for the confusion!
Andreas