I ran into an interesting, yet extremely annoying, bug on Visual Studio, below is the simplest repro: (uncomment the #define will allow VS to build the code)
#include <iostream>
using namespace std;
//#define BUILD_ON_VS
class CC
{
public:
template<typename T>
struct Foo
{
template<T foo>
void bar()
{
cout << "VC likes this!\n";
}
#ifndef BUILD_ON_VS
template<T foo>
void bar1();
#endif
};
Foo<int> m_foo;
};
#ifndef BUILD_ON_VS
template<typename T>
template<T foo>
void CC::Foo<T>::bar1()
{
cout << "VC doesn't like this...\n";
}
#endif
int main()
{
CC cc;
cc.m_foo.bar<-1>();
#ifndef BUILD_ON_VS
cc.m_foo.bar1<2>();
#endif
return 0;
}
Basically, I cannot put the definition of the function bar outside of the class in Visual Studio. bar and bar1 are exactly the same otherwise. Test on VS 2010 and VS 2012, both failed with errors:
error C2244: 'CC::Foo<T>::bar1' : unable to match function definition to an existing declaration
definition
'void CC::Foo<T>::bar1(void)'
existing declarations
'void CC::Foo<T>::bar1(void
It, however, works on all online compilers, such as compileonline and ideone.
I want to keep everything inside the cpp file, not in the .h to keep the code base clean.
Setting var1 to:
{
template<typename TT, TT foo>
void bar1();
}
template<typename T>
template<typename TT, TT foo>
void CC::Foo<T>::bar1()
{
}
Also works, but it makes the code looks idiotic by redefining the same template parameter and much more prone to bugs. It also makes the interface messy.