2013-10-11 18 views
7

私はC++でテンプレートを扱っています。 MSVCコンパイラでコンパイルしたときとMingw gccコンパイラを使用しているときに、テンプレートとフレンドクラスの使用に違いはありますか?私のコードは正常にコンパイルされ、MSVCでコンパイルされたときに望ましい出力が得られますが、gccでコンパイルするとエラーになります。以下は、この問題に対する可能な解決策になる可能性がどのようなC++テンプレートクラスは、コンパイラごとに異なる動作をします。

///////////Record.h///////////////////// 
#include "Base.h" 

class Derived1; 
class Derived2; 
template <class TYPE_LIST> class List; 

class FRecord 
{ 
public: 
    FRecord(); 
    virtual ~FRecord(); 

    friend class Base; 
#if _MSC_VER <= 1200 
    friend class List<Derived1>; 
    friend class List<Derived2>; 
#else 
    template <class TYPE_LIST> friend class List; 
#endif 
}; 

/////////////////////////////////////////////////////////////// 

///////////////////Base.h///////////////////////////////// 

class Base 
{ 
public: 
    Base(const HEADER *hc, const FRecord *fr); 
    virtual ~Base();  
    __inline bool IsNonValid() const; 

protected: 
    quint32 Size; 
}; 

///////////////////////////////////// 
// Data 
///////////////////////////////////// 
template <class TYPE_LIST> 
class Data : public TYPE_LIST 
{ 
public: 
    Data(const HEADER *hc, const FRecord *fr) : TYPE_LIST(hc, fr) 
    { 
     QString val = IsNonValid() ? "Non" : ""; 
     LOG0("Data ("<< val << " Valid)"); 
    } 

    virtual ~Data() 
    { 
     LOG0("Data deleted"); 
    } 
}; // Data 

/////////////////////////////////////////////////////////////////////////////////////// 

コンパイルするとMSVCで上記のコードは、所望の出力を与えるが、のMinGW GCCコンパイラでコンパイル時にエラーを以下与え、

Base.h:1154: error: there are no arguments to 'IsNonValid' that depend on a template parameter, so a declaration of 'IsNonValid' must be available 
Base.h:1553: error: 'Size' was not declared in this scope 

、私のコードです? ありがとうございます。

答えて

10

MSVCでは、2フェーズの名前検索が正しく実装されていません。このエラーを報告するにはGCCが正しいです。

原因は、テンプレートのパラメータに依存しない(VCの場合)テンプレートが定義されていて、インスタンス化されていないときに参照されるためです。

コンパイラは、IsNonValidが基本クラスから来ると言うことができないので、それはそれを知らないと正当に訴えます。 2つの解決方法があります

QString val = this->IsNonValid() ? "Non" : ""; 

// or 

QString val = TYPE_LIST::IsNonValid() ? "Non" : ""; 
  • に継承された名前を紹介:それは(潜在的に)テンプレートパラメータに依存コンパイラに明らかだよう

    1. は、IsNonValidへのアクセスを修飾します派生クラスのスコープ:

      template <class TYPE_LIST> 
      class Data : public TYPE_LIST 
      { 
      public: 
          using TYPE_LIST::IsNonValid; 
          // the rest as you had it originally 
      

    これらのどちらか名前に依存するようになり、したがって、TYPE_LISTという値が実際にわかっているときに、その検索までその検索が延期されます。

  • +0

    ありがとうございました@Angew:あなたの解決策は私の問題を解決しました。:)...どうすれば自分の質問のステータスを解決できますか? – user2765235

    +0

    @ user2765235問題を解決したと思われる回答を受け入れることでこれを行うには、回答の横にある緑色のチェックマークをクリックします。詳細については、[help](http://stackoverflow.com/help/accepted-answer)を参照してください。 – Angew

    7

    gccが正しい。インスタンス化の時間までルックアップを遅延させるには、this->を追加する必要があります。

    this->IsNonValid();

    MSVCは、それが適切に二相名の検索を実装していないとして、それはインスタンス化時まで、すべてのルックアップを遅らせることで、非適合されます。

    関連する問題