error C2244 on templated member variable with templated argument function, only happens on Visual Studio

末鹿安然 提交于 2019-12-10 23:31:45

问题


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.


回答1:


Found a fix by typing randomly and see if it compiles, haha!!! looks kind of stupid...

#include <iostream>
using namespace std;

//#define BUILD_ON_VS

class CC
{
public:

   template<typename T>
   struct Foo;

   Foo<int>* m_foo;

   template<typename T>
   struct Foo
   {
      template<T foo>
      void bar();
   };
};

template<typename T>
template<T foo>
void CC::Foo<T>::bar()
{
   cout << "VC happen to like this...\n";
}

int main()
{
   CC cc;
   cc.m_foo = new CC::Foo<int>;
   cc.m_foo->bar<2>();
}

I need to make an abstract class and instantiate it with template arguments;

Wonder why VC can't do this automatically like GCC.



来源:https://stackoverflow.com/questions/14631554/error-c2244-on-templated-member-variable-with-templated-argument-function-only

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!