Is it possible to eliminate the this pointer in a singleton?

4 days ago 1
ARTICLE AD BOX

This question is about the singleton pattern in modern C++ and one of its limitations in particular.

I can implement the singleton pattern like this:

class Logger { public: static Logger& instance() { static Logger singleton {}; return singleton; } Logger(const Logger&) = delete; auto operator= (const Logger&) = delete; // ... member functions declared here };

Now, consider some client code using the singleton:

void start() { auto& logger = Logger::instance(); logger.debug("start() called"); // ... }

My issue with this is: although singletons have only one instance, every member function call will require the compiler to pass the this pointer along with the arguments. This is wasteful. I could imagine that a procedural implementation of the logger, written in C, would outperform this singleton implementation.

For the same reason, C++23 allowed for operator () and [] to be declared static. Which avoids having to pass a this pointer with each call.

Theoretically, the compiler could optimize away the implicit this pointer argument, because its location is known at compile-time (the address of the local static variable). But I guess the compiler does not know.

Maybe this is more a discussion about language features than asking for an actual solution.

Update:

To make my case clearer, I have prepared an example in Compiler explorer. Comparing the singleton function call with that of the free function in the assembly:

Singleton:

mov esi, OFFSET FLAT:.LC0 mov rdi, rax call Logger::log_debug(const char*)

Free function:

mov edi, OFFSET FLAT:.LC0 call log_debug(const char*)

See what I mean? The free function call needs two instructions (in x86_64), whereas the singleton call needs three. The value returned by get_instance() will never change. Still, it is passed with every function call. This is what I meant by wasteful above.

Read Entire Article