2016-03-29 4 views
2

一部のWindowsのレガシーコードを移植し、私は完全には理解していない次のような問題に遭遇したのgcc /打ち鳴らすとコンパイルするためにそれを取得しようとしている間:構文パズル

template<typename T> class Base 
{ 
public: 
    Base() {} 

    T m_var; 
}; 

template<typename T> class Derived : public Base<T> 
{ 
public: 
    Derived() 
    { 
    #if 1 
     Base<T>::m_var = 0; // fix - compiles with gcc/clang now 
    #else 
     m_var = 0;   // original - compiles only with MSVC++ 
    #endif 
    } 
}; 

のgcc /打ち鳴らすの誤差は次のとおりです。

error: use of undeclared identifier 'm_var'

は、残念ながら、修飾されていないメンバ変数は、派生クラスのメソッドで参照されている場所の何百もある、と私は本当にそのように、これらすべてを変更する必要がありますする必要はありません彼らはの資格を持っていますもし私がそれを助けることができれば。

gcc/clangがMSVC++で必要としない理由を誰もが説明でき、可能な回避策を提案できますか?

答えて

5

Base<T>は従属ベースであるため、メンバーには修飾されていない参照からアクセスできません。ご存知のように、Base<T>::m_varからアクセスできます。別のオプションはthis->m_varです。

私はそこに簡潔な回避策があるかどうかはわかりません。 1つのオプションは、T& m_var;データメンバーをDerivedに追加し、それを参照Base<T>::m_varに初期化することです。余分なリファレンスメンバーと一緒に暮らすことができない場合は、T& m_var = this->m_var;を未修飾のm_varアクセス権を持つ関数の先頭に追加することができます。

+0

簡潔な説明をお寄せいただきありがとうございます。おそらくMSVC++は苦情なしでこれをコンパイルするのに間違っていますか? –

+1

@PaulR可能性が高い、はい。数年前、g ++はこの種のコードについては不平を言っておらず、ルールの実行を開始したときに同様のコードを修正しなければならないことを漠然と思い出しました。 – anderas

+1

@PaulRええ、それは二相検索の欠如のためです。メンバーはインスタンス化時に検索され、テンプレート定義がAFAIKにチェックされると無視されます。 – TartanLlama

2

@TartanLlamaが述べたように、メンバは、テンプレートパラメータに依存する基本型のため、非修飾ルックアップによって利用できません。別にBase<T>::m_varまたはthis->m_varとしてそれをアクセスするから、それはあなたがアクセスできるようにしたい各クラスのメンバーのために一度だけ入力する必要があるので、私は強く好む回避策があります:

単にDerivedのクラス定義にusing Base<T>::m_var;を追加します。このようにして、通常の名前検索によってm_varが見つかります。

+0

回避策を提案してくれてありがとう - この使用例では、「使用しています」という考え方は完璧です。これは、派生したすべてのメソッドを屠殺するのを避けることができるということを意味しています。 –

+1

ええ、これをやって、私はばかだ。 – TartanLlama

+1

@PaulRよろしくお願いします!申し訳ありませんが、それぞれの用語をやや緩やかな/非標準的な方法で使用することがあります。私はここの標準言語に慣れていません... – anderas