Why does a static namespace variable accessed from inside an inline class method work?

c++, static

Solution

Your code is only correct if you only ever include this header in a single source file.

Because `uid` is declared as `static`, it has internal linkage. There is one instance of the `uid` variable per source file in which this header is included. If you include this header in three source files, there will be three `uid` variables.

The `getUid` function is implicitly `inline` because it is defined inside of the class definition. The fact that it is a `static` member function is irrelevant. The rule for `inline` functions is that an `inline` function must be defined in every source file in which it is used, and that all of the definitions must be identical.

Your `getUid` function definition violates this rule: yes, it is defined in every source file that includes the header (because it is defined in the header), but each definition is different, because in each definition the `uid` referred to is a different `uid` variable.

Therefore, your program violates the One Definition Rule and exhibits undefined behavior. The particular behavior you observe is likely because the compiler picks one definition of the inline function and just discards the rest, so the "global variable" that you think you are using just happens to be one of the `uid` variables--whichever one was referenced by the copy of `getUid` that the compiler kept. While this is a typical manifestation of this form of undefined behavior, the behavior is nonetheless undefined.

You can make the `uid` variable function-local to ensure that there is exactly one instance, and to avoid violating the One Definition Rule:

namespace NS {
  class X {
  public:
    static int getUID() {
      static int uid = 0;
      return uid++;
    }
  };
}

It is guaranteed in this case that there will be exactly one instance of `uid` in the program.

Problem

I saw this code recently in a header file, and was surprised that it worked: ``` namespace NS { static int uid = 0; class X { public: static int getUID() { return uid++; } }; } ``` If the static method `NS::X::getUID()` is called from several different C++ source files, I was surprised to find that it correctly generated a unique ID (unique across translation units). I thought that a static variable in a namespace scope had internal linkage to the translation unit. What's going on here? Does the inline static method in class X have it's own translation unit, and that's why it generates a unique ID? Or is it working for me due to a quirk in my compiler? Does the above code rely on "safe" well-defined behavior? If so, this is a surprisingly concise method of generating a Unique ID in an inline or template class, even if it looks a bit kludgy. Or is it better to generate a new C++ source file for a static unique ID function like this, and move the static ID inside the class? Update: For a test case, I wrote several functions like this in different files (file1.cpp, file2.cpp, etc.): ``` #include "static_def.h" // Name of the above header file. void func1() { int uid1 = NS::X::getUID(); int uid2 = NS::X::getUID(); std::cout << "File1, UID1: " << uid1 << ", UID2: " << uid2 << std::endl; } ``` The suprising output (after calling these from main) was: ``` File1, UID1: 0, UID2: 1 File2, UID1: 2, UID2: 3 ```

Original source