7

C++ でテンプレートを使用しています。MSVC コンパイラでコンパイルした場合と Mingw gcc コンパイラを使用した場合で、テンプレートとフレンド クラスの使用に違いはありますか。私のコードは、MSVC でコンパイルすると正常にコンパイルされ、目的の出力が得られますが、gcc でコンパイルするとエラーが発生します。以下は私のコードです、

///////////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

この問題の可能な解決策は何ですか? 前もって感謝します。

4

2 に答える 2

11

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

原因は、テンプレートのパラメーターに依存しないテンプレート内で使用される名前が (VC の場合にあるはずです)、インスタンス化されたときではなく、テンプレートが定義されたときに検索されることです。

あなたの場合、コンパイラはそれIsNonValidが基本クラスから来ることを伝える方法がないので、それを知らないと不平を言うのは当然です。考えられる解決策は 2 つあります。

  1. へのアクセスを修飾しIsNonValidて、テンプレート パラメータに (潜在的に) 依存していることがコンパイラに明確になるようにします。

    QString val = this->IsNonValid() ? "Non" : "";
    
    // or
    
    QString val = TYPE_LIST::IsNonValid() ? "Non" : "";
    
  2. 継承された名前を派生クラスのスコープに導入します。

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

TYPE_LISTこれらのいずれも名前を依存させるため、 の値が実際にわかっているインスタンス化までルックアップを延期します。

于 2013-10-11T13:04:18.253 に答える