2

Visual Studioで興味深い、しかし非常に厄介なバグに遭遇しました。以下は最も単純な再現です:(コメントを外すとVSがコードをビルドできるようになります)

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

基本的に、VisualStudioのクラスの外に関数バーの定義を配置することはできません。それ以外の点では、barとbar1はまったく同じです。VS2010とVS2012でテストしましたが、どちらもエラーで失敗しました。

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

ただし、compileonlineやideoneなどのすべてのオンラインコンパイラで動作します。

コードベースをクリーンに保つために、.hではなくcppファイル内にすべてを保持したいと思います。

Setting var1 to:
{
   template<typename TT, TT foo>
   void bar1();
}

template<typename T>
template<typename TT, TT foo>
void CC::Foo<T>::bar1()
{
}

これも機能しますが、同じテンプレートパラメータを再定義することでコードがばかげているように見え、バグが発生しやすくなります。また、インターフェイスが乱雑になります。

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 に答える