I have a class in a library, if that class has a template method which has a static variable, using the method from within the library will access a different static variable than using the method from outside the library. This behavior happen in windows, in linux it works as expected. I prepared an example with two scenarios, in both scenarios classes are defined in a library (LibA) and the test program is linked to it (temptest). Code is simplified in this explanation, full code is available in this github repository https://github.com/pyaggi/temptest. Example code uses cmake, so it will be easy to compile in any platform.
1- Scenario with a class template
//liba.h (library)
template<typename T>
class TestClass_template
{
public:
TestClass_template()
{
}
template<typename T1>
static T1 incCounter()
{
static T1 counter=0;
return counter++;
}
private:
T val;
};
class LIBA_PUBLIC TestClass_long:public TestClass_template<long>
{
public:
TestClass_long();
static short test_incCounter_short();
};
//liba.cpp (library)
TestClass_long::TestClass_long()
{
}
short TestClass_long::test_incCounter_short()
{
return incCounter<short>();
}
//main.cpp (temptest, program)
std::cout<<"Output from class template example"<<std::endl;
for (int c=0;c<2;c++)
{
std::cout<<"TestClass<long>::incCounter_short "<<TestClass_template<long>::incCounter<short>()<<std::endl;
TestClass_long::test_incCounter_short();
std::cout<<"TestClass_long::incCounter_short "<<TestClass_long::incCounter<short>()<<std::endl;
TestClass_long::test_incCounter_short();
}
Output in Linux
Output from templated class example
TestClass<long>::incCounter_short 0
TestClass_long::incCounter_short 2
TestClass<long>::incCounter_short 4
TestClass_long::incCounter_short 6
Ouput in Windows
Output from templated class example
TestClass<long>::incCounter_short 0
TestClass_long::incCounter_short 1
TestClass<long>::incCounter_short 2
TestClass_long::incCounter_short 3
In windows calling TestClass_long::test_incCounter_short(); access a different static variable producing a sequencial output (0,1,2,3) in linux it access the same static hence producing an interleaved output (0,2,4,6).
2- Scenario with a regular class
//liba.h (library)
class LIBA_PUBLIC TestClass
{
public:
TestClass()
{
}
template<typename T1>
static T1 incCounter()
{
static T1 counter=0;
return counter++;
}
static short test_incCounter_short();
private:
long val;
};
//liba.cpp (library)
short TestClass::test_incCounter_short()
{
return incCounter<short>();
}
//main.cpp (temptest, program)
std::cout<<"Output from regular class example"<<std::endl;
for (int c=0;c<2;c++)
{
std::cout<<"TestClass::incCounter_short "<<TestClass::incCounter<short>()<<std::endl;
TestClass::test_incCounter_short();
std::cout<<"TestClass::incCounter_short "<<TestClass::incCounter<short>()<<std::endl;
TestClass::test_incCounter_short();
}
Output in Linux
Output from templated class example
TestClass::incCounter_short 0
TestClass::incCounter_short 2
TestClass::incCounter_short 4
TestClass::incCounter_short 6
Ouput in Windows
Output from templated class example
TestClass::incCounter_short 0
TestClass::incCounter_short 1
TestClass::incCounter_short 2
TestClass::incCounter_short 3
Linux test was performed with g++ and clang.
Windows test was performed with msvc(cl.exe) and clang (msvc-cl.exe).
So I have two questions:
1- What is the expected behavior according to C++17 ?
2- Is it possible to make MSVC behave like linux ?