2012-07-01 4 views
8

Possible Duplicate:
GCC problem : using a member of a base class that depends on a template argumentKonstanten in Template-Klassen definiert

Ich dachte, ich war vertraut mit C++, aber anscheinend nicht genug vertraut.
Das Problem ist, wenn Sie eine Konstante in einer Vorlagenklasse definieren, können Sie die Konstante in neuen Klassen verwenden, die von dieser Klasse abgeleitet sind, aber nicht Vorlage Klassen, die davon abgeleitet sind.

Zum Beispiel sagt gcc

test.h:18: error: ‘theconstant’ was not declared in this scope

wenn ich versuche, diese (vereinfacht) Header-Datei zu kompilieren:

#pragma once 

template <typename T> class base 
{ 
    public: 
    static const int theconstant = 42; 
}; 

class derive1 : public base<size_t> 
{ 
    public: 
    derive1(int arg = theconstant) {} 
}; 

template<typename T> class derive2 : public base<T> 
{ 
    public: 
    derive2(int arg = theconstant) {} // this is line 18 
}; 

Das Problem ist also, dass eine Klasse, derive1, fein kompiliert, aber die andere Klasse, derive2, die eine Template-Spezialisierung ist, nicht.
Nun vielleicht gcc's Fehler ist nicht klar genug, aber ich verstehe nicht, warum der Konstruktor in derive2 einen anderen Umfang als der in derive1 haben würde.
Falls es darauf ankommt, geschieht dies beim Kompilieren der Headerdatei selbst, nicht beim Instanziieren eines Objekts vom Typ derive2<type>.

Ich weiß auch, was zu ändern, um dies zu kompilieren, so dass ich nicht wirklich nach einzeiligen Code als Antworten suchen. Ich möchte verstehen, warum dies passiert! Ich habe versucht, das Internet zu durchsuchen, aber anscheinend verwende ich nicht die richtigen Suchargumente.

+0

FWIW, der gleiche Code kompiliert in VC++ 2010 gut. Dies könnte ein Fehler in GCC sein ... – dsharlet

+0

'here2 (int arg = Basis :: theconstant) {}' kompiliert gut. – jrok

+0

@dsharlet - kein Fehler im GCC-Teil, wie in der Spezifikation beschrieben. – Flexo

Antwort

2

Ich bin mir ziemlich sicher, dass dies hilft Ihnen zu verstehen:

Ihr Code der nicht kompiliert:

template<typename T> class derive2 : public base<T> 
{ 
    public: 
    derive2(int arg = theconstant) {} // this is line 18 
}; 

Und der Grund, warum:

template <> class base<size_t> 
{ 
    public: 
    static const int ha_idonthave_theconstant = 42; 
}; 
derive2<size_t> impossible_isnt_it; 

Die Spezialisierung !!! Der Compiler in Ihrer Zeile 18 kann nicht sicher sein, dass Sie die Basis <> nicht so spezialisieren werden, dass diese Konstante dort überhaupt nicht vorhanden ist.

+0

Das macht so viel Sinn, dass ich mich frage, warum es mir nicht eingefallen ist ... Ich habe es mit einer spezialisierten Vorlage versucht, die nur das gleiche Mitglied mit einem anderen Wert enthält, und ich konnte es nicht funktionieren lassen. Naja. Vielen Dank! –

2

Versuchen

template<typename T> class derive2 : public base<T> 
{ 
    public: 
    derive2(int arg = base<T>::theconstant) {} // this is line 18 
}; 

Grundsätzlich Sie den unvollständigen Rahmen für den "theconstant" angegeben haben.

+0

Ja, das wurde in den Kommentaren erwähnt. Aber ich möchte verstehen, warum dies in "abgeleitet2" und nicht in "abgeleitet1" notwendig ist, auch wenn die Vererbung nicht mehrdeutig ist. Inwiefern ist der Umfang unvollständig? –

+1

Ich denke, es hat etwas mit der "faulen" Template Instanziierung zu tun. Es gibt _no_ 'base'-Klasse, die dem Compiler zu dem Zeitpunkt bekannt ist, zu dem er' theconstant 'in derivate2 analysiert. Sobald Sie die Basis verwenden, zwingen Sie den Compiler, sich mit der Basis vertraut zu machen. <> –

+0

Ich muss darüber nachdenken. –