0

In practices singleton pattern is created with simple static function that returns one local static variable. As long as the instance is static it returns the same variable defined once during first function call.

The confusing part for me is that if I declare normal static function with static local variable in one header file and include that header in two different translation unit when they call that function the function local static variable is constructed twice - each for each translation unit.

The reason is that with static function identifier function linkage is internal so there are two instances of that functions for each translation unit (source file) and thus there are two local instances for that static variable.

My question is why doesn't that same logic apply to singleton pattern? When we declare static function why isn't it internally linked and thus why doesn't it create two instances of local static variable (which by definition is the only singleton instance) ?

singleton main function I'm talking about:

static className& instance() { static className instance; return instance; }
  • There are couple of issues at play here -- non-member functions vs member functions and inline functions vs non-inline functions. Please add some demonstrative code to your post to make your questions clearer. At it stands, we can only speculate what your code looks like. – R Sahu Apr 24 '19 at 18:13
  • You seem to be missing the key point here - the function is `static` in the class. Static members of a class are very different from free-standing static functions. – SergeyA Apr 24 '19 at 18:14
  • Related: https://stackoverflow.com/questions/29224679/c-static-keyword-vs-c-private-scope – πάντα ῥεῖ Apr 24 '19 at 18:55

2 Answers2

1

Because static [dcl.stc]/4 doesn't always mean internal linkage. When applied to a normal, namespace-scope function such as

static void fun();  // fun has internal linkage

the static specifier declares this function to have internal linkage [basic.link]/5. This is mainly there for backwards compatibility with C. In C++ you'd better use an unnamed namespace to declare entities with internal linkage to avoid precisely the kind of confusion that lead to your question:

namespace
{
    void fun();  // fun has internal linkage, C++ style
}

When applied to a member function of a class, the static specifier declares the function to be a static member function of that class, i.e., a function that does not operate on instances of that class but is just a normal function declared in the scope of that class, for example:

class X
{
public:
    static void fun();  // fun is a static member function with external linkage
};

void test()
{
    X::fun();  // invoke fun
}

Linkage of a non-namespace-scope function such as a static member function is not affected by the keyword static. As a result, the static member function above will have external linkage [basic.link]/6.

Apart from all that: the Singleton pattern is almost certainly not going to be the right choice for what you want to do. Don't do it.

Michael Kenzel
  • 15,508
  • 2
  • 30
  • 39
  • I believe you didn't really answer my question. Question is why 'static' keyword doesn't make that function internally linked for each translation unit and, accordingly, create separate local static class variable for each object file ? :) – shota silagadze Apr 24 '19 at 18:45
  • @shotasilagadze Based on the information in your question above, I assumed that the function in question must be a member function of the singleton class. Is this not the case? – Michael Kenzel Apr 24 '19 at 18:47
  • yes, but why membership makes this function different from ordinary static functions with internal linkage? – shota silagadze Apr 24 '19 at 19:39
  • @shotasilagadze because that's what the `static` keyword does in C++, as explained in my answer above. To normal namespace-scope functions, it gives internal linkage, because that's what it does in C, and C++ just kept that for compatibility reasons. Member functions it turns into static member functions without any effect on linkage. I don't really think there's anything more that can be said to that, you'll even find links up there to the paragraphs [dcl.stc]/4 [basic.link]/5 which specify precisely this behavior… – Michael Kenzel Apr 24 '19 at 20:00
  • so you are saying that when static function is member of a class it doesn't become internally linked so translation units "see" the only instance of that function ? and accordingly the only local static variable? – shota silagadze Apr 24 '19 at 20:19
  • @shotasilagadze yes, exactly. – Michael Kenzel Apr 24 '19 at 20:19
-1

The function that returns the singleton should not be static, only the singleton itself.

This would be incorrect

//header file - bad implementation of singleton pattern

class foo {/*stuff*/};

static foo& getFoo() {
    static foo myFoo;
    return myFoo;
}

This implementation would result in a different myFoo being returned in each compilation unit, since each compilation unit has its own getFoo function

What you should do is this:

//header file - good implementation of singleton pattern

class foo {/*stuff*/};

foo& getFoo();

//source file - good implementation of singleton pattern

foo& getFoo() {
    static foo myFoo;
    return myFoo;
}

Now each compilation unit will reference the same getFoo function and get the same singleton (since the function is not static)


As a testable example to show this.

//foo.h
#include <iostream>

static void print_num_times_called() {
    static int num_times_called = 0;
    ++num_times_called;
    std::cout << num_times_called << "\n";
}

void call_print_num_times_called();

//foo.cpp
#include "foo.h"

void call_print_num_times_called() {
    print_num_times_called();
}

//main.cpp
#include "foo.h"

void main() {
    for (int i = 0; i < 10; ++i) {
        print_num_times_called();
    }
    for (int i = 0; i < 10; ++i) {
        call_print_num_times_called();
    }
}

//output

1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
rtpax
  • 1,687
  • 1
  • 18
  • 32
  • the problem is that first (as mentioned wrong) version returns the same instance :) that's why I'm confused – shota silagadze Apr 24 '19 at 18:25
  • _@rtpax_ What you're telling here is complete nonsense, sorry. – πάντα ῥεῖ Apr 24 '19 at 18:32
  • _"since each compilation unit has its own getFoo function"_ That's not true. – πάντα ῥεῖ Apr 24 '19 at 18:45
  • @πάνταῥεῖ I gave an example that shows unequivocally that static functions are treated separately in separate compilation units. If they were not, you would get the shown output. What part of this answer is "nonsense"? – rtpax Apr 24 '19 at 19:09
  • try singleton pattern I described above ... in that case local static instance is the same for translation units look at that pattern https://stackoverflow.com/questions/1008019/c-singleton-design-pattern – shota silagadze Apr 24 '19 at 19:45
  • Alright, we're talking about completely different kinds of `static` then. Static member functions have external linkage. Nothing special about singleton pattern specifically, just a confusing reuse of the `static` keyword. – rtpax Apr 24 '19 at 20:04