c++ Play it only once Sam

Just how many times you had admitted to yourself? It was rather foolish to think of globals in C++ as “a simple thing” :) After all: “What could possibly go wrong”tm ? If you know what I am talking about please proceed.

As it turns out many things can and will go wrong. With what you might think of, as C++ global variables and functions and other “things”. I am sure every now and then, you are wondering why is this singleton not a singleton, or why is this function called more than once,  and how it is, that nobody seems to care?

After many years of various coding idioms, that handle static linkage and global variables, and the famous “Singleton Pattern” implementations, may I be so bold to remind you: you do not have to dance around these issues anymore.

That was 2018 after all

As from C++11 you had a new memory model to enjoy. And from C++17 you had them inline variables too.

Since the C++ primordial soup, you have local statics. Aka static local variables.  And as if this would be an end to this list of crucial C++ ingredients,  there are one more: lambdas.

Please do not forget the big gotcha: Internal linkage and anonymous namespace’s.

So you are thinking now: What is this post? Reminding us of the whole of standard text? Is that it?

Well, no my dear readers. Humble myself has prepared yet another delicious little nugget for you to readily copy-paste into your code. Here it comes:

Please observe carefully the above:

  • the big gotcha first: anonymous namespace implies default static linkage for variables inside. Thus do not put this code inside it. This is the header code. This dbj_once namespace deliberately has a name.
    If this would be anon. namespace variables inside will be treated as if they are static. Which will make things to be called as many times as you have compilation units. Aka “cpp files”.
    Effectively inline singleton & instance(), will be linked as: static singleton & instance(). Please make sure to devote some time to the  “Internal linkage” and anon. namespace’s subject.
  • Lock-Free. Since C++11, this is safe in presence of multiple threads (MT) and is supported as such by all major compilers. No std::mutex or another kind of locking is necessary.
  • Call Once Mechanism. Inside instance() , is an anonymous lambda that is guaranteed to be called only once.
  • This coding idiom is safe to use in header only situations. Very important for modern and standard C++.

Please do remember: until C++11, to achieve the same, this was much more involved. Much more.

Now (one might ask) why not just using std::call_once ?  Or if you are WIN32 aficionado, why no just use InitOnceExecuteOnce() a function?  These two btw.  are clearly illustrating what do I mean by “it was much more involved”, in them bad old days before C++11.

You can, but you do not have to use the legacy singleton idioms. It is as simple as that. The code presented here is standard C++ and does it all, for you.


Let us think. Compile-time singleton would be much more “singleton logical”. Unique things are unlikely to come and go dynamically at runtime.  They can but are unlikely.

Computer parts represented as singletons are one example. Monitor as a singleton instance is unlikely to disappear at runtime. But. It can.

So let’s code following those requirements. User view would be this:

Fully functional and working code is on a Godbolt.

Enjoy, study and come back to us with questions. But.

We need to talk about the beast

And that is modern C. It keeps churning out simpler, cleaner, faster and easier to maintain solutions.

How would one solve the above conundrum using modern C?  Let us push you into the deep end of the pools:

That is one simple and easy to maintain solution. From consistent requirements to a consistent solution. In C, one produces programs, not abstractions from which programs might be built.

C executables are fast, small and resilient.

Here is the mandatory Godbolt.




%d bloggers like this: