How does static member behave across multiple files?

I am testing static member variables on Windows using Visual Studio 2015. The project comprises three .cpp and one header:

StaticHeader.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#pragma once
#include <iostream>

template <typename T>
class TempClass {
public:
	static T m_Static;
	static void Inc() {
		m_Static++;
	}
	static void Dec() {
		m_Static--;
	}
	static void StaticFunc();
	static void showStatic();
};

template <typename T>
void TempClass<T>::showStatic() {
	std::cout << "###" << m_Static;
}


StaticCpp1.cpp:
1
2
3
4
5
6
7
8
9
10
#include "StaticHeader.h"

template <typename T>
T TempClass<T>::m_Static = 1;

template <class T> void TempClass<T>::StaticFunc() {
	Inc();
}

template class TempClass<float>;


StaticCpp2.cpp:
1
2
3
4
5
6
7
8
9
10
#include "StaticHeader.h"

template <typename T>
T TempClass<T>::m_Static = 100;

template <class T> void TempClass<T>::StaticFunc() {
	Dec();
}

template class TempClass<float>;


Main.cpp:
1
2
3
4
5
6
7
8
9
#include "StaticHeader.h"

template <typename T>
T TempClass<T>::m_Static = 4.5;

int main() {
	TempClass<float>::StaticFunc();
        TempClass<float>::showStatic();
}


The above code can be compiled and linked in VS2015. I then use the debugger to trace the code and found that the statement TempClass<float>::StaticFunc(); always goes into the StaticFunc() function in StaticCpp1.cpp. So my first question is:
(1) When the two source file StaticCpp1.cpp and StaticCpp2.cpp are essentially the same, why does the compiler choose the former over the latter?

Then I removed the m_Static definition in both Main.cpp and StaticCpp1.cpp. The program still goes into StaticCpp1.cpp, but print out 101, showing that it is the static variable defined in StaticCpp2.cpp that is used. So my second question is:
(2) By default, if we defined a normal (not a member of a class) static variable , it has only internal linkage, meaning that it can be seen only in the .cpp source file defining it. Based on this rule, StaticCpp1.cpp should not be able to see the static variable defined in StaticCpp2.cpp. But why is StaticCpp1.cpp able to see it in StaticCpp2.cpp? Is global linkage the default for static member?

And my third question is:
(3) With the original code, is the static member variable unique, i.e., there is only one copy of TempClass<T>::m_Static in memory? Or there is one for each .cpp?

To avoid mess, I am talking about Visual Studio 2015 on Windows 10 version 1803.

Thank you.
(1) The point of template is that the first matching definition is used. When a templated expression is resolved no further action will be taken. Therefore it depends on the compiler which template expression is finally chosen.

(2) It has external linkage. See:

https://en.cppreference.com/w/cpp/language/static

(3) A template does not contribute to the final executable unless it used/resolved
Just to confirm, combining answers to (1) and (3), all subsequent matches of template definition do not contribute to the final executable, so there is exactly only one instance of m_Static in memory. Right?

I think if you had
classname<int> a and classname<double> b combined with
T TempClass<T>::m_Static = 4.5;

that you have 2 resolutions of the class, and because the static variable is of the template type, it would make 2 copies of it with different types, they won't be shared. If you had instead
classname<int> a; classname<int> b; you would only have 1 copy, as it already resolved it for the int type (this is what you asked).


if the type of the static were double instead of template type... I do not know what it would do (would it share across a double template and an int template version? ) I suspect you get 2 copies, but someone else may know if that is wrong.

Last edited on
Topic archived. No new replies allowed.