The following code, which has 2 definitions for a template static field member, each definition defines template1<int>::x
with a different value.
One would expect the linker to reject such redefinitions as they have different values.
But compilation & linkage passes for both g++ and MSVC, and which definition is used is dependent on the order in which the sources are passed to the linker.
Is this behavior compliant to the C++ standard, undefined behavior, or a linker bug?
my_template.h
template <class T>
class template1
{
public:
static int x;
};
Src2.cpp
#include <stdio.h>
#include "my_template.h"
template <class T>
int template1<T>::x = 2;
void my_func() // definition
{
printf("my_func: template1<int>::x = %d\n", template1<int>::x); // definition of X to 2.
printf("my_func: template1<char>::x = %d\n", template1<char>::x); // definition of X to 2.
}
Main.cpp
#include <cstdio>
#include "my_template.h"
template <class T>
int template1<T>::x = 1;
void my_func();
int main()
{
printf("main: template1<int>::x = %d\n", template1<int>::x); // definition of X to 1.
my_func();
return 0;
}
Compile with g++ (MinGW.org GCC Build-20200227-1) 9.2.0+
Compile1
g++ -o prog Src2.cpp Main.cpp
Output1
main: template1<int>::x = 2
my_func: template1<int>::x = 2
my_func: template1<char>::x = 2
Compile2
g++ -o prog Main.cpp Src2.cpp
Ouput2
main: template1<int>::x = 1
my_func: template1<int>::x = 1
my_func: template1<char>::x = 2
Observed also with
Microsoft (R) C/C++ Optimizing Compiler Version 19.25.28612 for x86
When I disassembled the code with -S
flag, each compilation unit defined the same symbol name.
Co-work with Nightra.
This violates ODR (which requires that an entity must have exactly one definition, if it's used). So the program has UB.
The compiler couldn't diagnose this, because each translation unit is fine. In theory, the linker could diagnose this, but in practice it won't do that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With