2013-10-11 8 views
7

Ich arbeite mit Vorlagen in C++. Gibt es einen Unterschied in der Verwendung von Templates und der Friend-Klasse, wenn sie mit dem MSVC-Compiler kompiliert werden und wenn der Mingw-gcc-Compiler verwendet wird. Mein Code kompiliert erfolgreich und gibt die gewünschte Ausgabe, wenn mit MSVC kompiliert wird, aber es gibt Fehler, wenn mit Gcc kompiliert wird. Unten ist mein Code,C++ Template-Klasse verhält sich für verschiedene Compiler unterschiedlich

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

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

Wenn der obige Code mit MSVC kompilierte Ausgabe gewünscht ergibt aber, wenn sie mit Mingw GCC-Compiler kompiliert gibt sie Fehler folgende,

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 

Was die mögliche Lösung für dieses Problem sein könnte ? Vielen Dank im Voraus.

Antwort

10

MSVC implementiert zweiphasige Namenssuche nicht korrekt. GCC hat diesen Fehler korrekt gemeldet.

Die Ursache ist, dass in einer Vorlage verwendete Namen, die nicht von den Parametern der Vorlage abhängen (sollten im Falle von VC sein), wenn die Vorlage definiert ist, nicht wenn sie instanziiert wird.

In Ihrem Fall hat der Compiler keine Möglichkeit zu sagen, dass IsNonValid von der Basisklasse kommen wird, also beklagt es sich zu Recht, es weiß es nicht. Es gibt zwei mögliche Lösungen:

  1. Qualifizieren den Zugang zu IsNonValid, so dass es mit dem Compiler (potentiell) klar ist, hängt von den Template-Parameter:

    QString val = this->IsNonValid() ? "Non" : ""; 
    
    // or 
    
    QString val = TYPE_LIST::IsNonValid() ? "Non" : ""; 
    
  2. Einführung der geerbten Namen in der Umfang der abgeleiteten Klasse:

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

Beides macht den Namen abhängig und verschiebt somit sein Nachschlagen bis zur Einführung, wenn der Wert tatsächlich bekannt ist.

+0

Dank @Angew: Ihre Lösung löste mein Problem.:)..Jetzt wie kann ich den Status meiner Frage zu Gelöst geändert? – user2765235

+0

@ user2765235 Durch die Annahme der Antwort, die Sie für die Lösung des Problems halten. Klicken Sie dazu auf das grüne Häkchen neben der Antwort. Weitere Informationen finden Sie in der [Hilfe] (http://stackoverflow.com/help/accepted-answer). – Angew

7

gcc ist korrekt. Sie müssen this-> hinzufügen, um die Suche bis zur Instanziierungszeit zu verzögern.

this->IsNonValid();

MSVC ist nicht konforme, dass sie alle Lookups bis Instanziierung Zeit verzögert, da es nicht richtig zweiphasige Namenssuche nicht implementiert.