2

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.

4

1 回答 1

1

通过随机输入找到一个修复,看看它是否编译,哈哈!看起来有点傻……

#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>();
}

我需要创建一个抽象类并使用模板参数对其进行实例化;

想知道为什么 VC 不能像 GCC 那样自动执行此操作。

于 2013-02-12T17:18:26.067 回答