gängige Anfänger-Fehler?
-
ach bestimmt ein internal compiler error. aber warum? sehe den fehler nicht.
-
sehe den fehler nicht
Es fehlt die, in diesem Fall leere, Parameterliste.
// so ist's richtig Foo::~Foo() {}
-
HumeSikkins schrieb:
Und ein Fehler, der von kaum einem Compiler erkannt wird:
template <class T> struct Foo { int i; }; template <class U> struct Bar : public Foo<U> { void func() { i = 22; } };
um ehrlich zu sein, habe ich den Sinn auch nie verstanden... da i nicht in Bar enthalten ist, müsste er IMHO als nächstes in Foo<U> suchen. Was viele Compiler auch so machen. Du weisst nicht zufällig warum man hier this->i stattdessen schreiben muss?
-
Du weisst nicht zufällig warum man hier this->i stattdessen schreiben muss?
Ich wäre ein Gugelhupf, wenn ich den Ursprung eines mir bekannten Fehlers ignorieren würde
Die Antwort findest du in 14.6.2.8:
in the definition of a class template [...], if a base class of this template depends on a template parameter, the base class scope is not examined during name lookup until the class is instantiated.
Der base class scope wird also schon mal nicht berücksichtigt. Da i nun aber kein abhängiger Name ist, wird die Gültigkeit von i bereits in der ersten Phase der Templateprüfung getestet. Es gibt hier kein bekanntes i -> Fehler.
Durch die Qualifizierung mit this-> oder Foo<U>:: wird i ein abhängiger Name und erst bei der Instanziierung des Templates geprüft -> Kein Problem.
Nötig ist das Ganze um spätere explizite oder partielle Spezialisierungen der Basisklasse unterstützen zu können.
Ich habe dazu am 9.5.2002 schon mal einen ewig langen Beitrag geschrieben, dessen Wiederholung hier aber nicht lohnt
-
HumeSikkins schrieb:
Nötig ist das Ganze um spätere explizite oder partielle Spezialisierungen der Basisklasse unterstützen zu können.
Genau das interessiert mich. Den 'Grund' - weil es so im Standard steht - kannte ich. Mich interessiert es aber, WARUM es so im standard steht
Kannst du zB ein minimalbeispiel machen? Oder einen Link posten? Danke
Ich habe dazu am 9.5.2002 schon mal einen ewig langen Beitrag geschrieben, dessen Wiederholung hier aber nicht lohnt
Ähm... Ich habe gesucht, aber das einzige was ich von dir Gefunden habe war am 8.5. bezüglich eines Umzugs... Sorry
Du weisst nicht zufällig den Titel des Threads?
-
Ich habe gesucht, aber das einzige was ich von dir Gefunden habe war am 8.5. bezüglich eines Umzugs... Sorry
2002?
Du weisst nicht zufällig den Titel des Threads?
Das Thema hieß: "Compilerumfrage"
Mich interessiert es aber, WARUM es so im standard steht Kannst du zB ein minimalbeispiel machen?
So wie ich das sehe, braucht man diese Regel hauptsächlich im Zusammenhang mit der zweistufigen Templateprüfung, wie sie im Standard beschrieben steht.
Würden unabhängige Namen auch im Basisklassenscope einer von einem Templateparameter abhängigen Templatebasisklasse gesucht werden, dann würden solche Namen zu früh gebunden werden. Eine spätere Spezialisierung der Basisklasse könnte diese Bindung aber ungültig machen:// Meine Lib.h template <class T> struct Base { void foo() {} }; template <class T> struct Derived : public Base<T> { void bar() { foo(); } }; // Irgendwo in Deine Lib.h template <> struct Base<int> { }; int main() { Derived<int> d; d.bar(); }
Ein Compiler der Templates immer erst bei der Instanziierung prüft (wie z.B. der VC 6.0) kann in solch einem Fall die oben genannte Regel ignorieren. Er wird trotzdem den richtigen Code generieren, da er ja zum Zeitpunkt der Instanziierung insbesondere auch die Spezialisierung kennt.
Zu einem wirklichen Problem wird es, wenn ein Name an eine freie Funktion gebunden ist, eine spätere Spezialisierung einer Basisklasse aber eine Methode mit selben Namen einführt. Würde die genannte Regel nicht existieren, würde damit die vorherige Bindung aufgehoben werden, da der Basisklassenscope schließlich "näher dran" ist als der globale Scope.
Minimalbeispiel:
#include <cassert> // Meine Lib.h void aFunction() {} template <class T> struct Base {}; template <class T> struct Derived : public Base<T> { void foo() { aFunction(); // ::aFunction } }; // Irgendwo in Deine Lib.h template <> struct Base<int> { void aFunction() // Ups { assert(false); } }; int main() { Derived<int> d; d.foo(); }
Ein Compiler der die Regel nicht berücksichtigt wird hier die Methode aufrufen und damit das Programm beenden. Ein konformer Compiler hingegen ignoriert den Basisklassenscope und bindet den unabhängigen (unqualifizierten) Namen aFunction immer an die freie Funktion, egal was du oder ich mit dem Basisklassentemplate machen.
-
Ich wette, das der hier so ausführlich besprochene Fehler nicht nur ein Anfängerfehler ist, sondern auch Fortgeschrittene ihn nicht erkenne werden.
-
Helium schrieb:
Ich wette, das der hier so ausführlich besprochene Fehler nicht nur ein Anfängerfehler ist, sondern auch Fortgeschrittene ihn nicht erkenne werden.
Ja. Tut mir leid. Ich hatte das "Anfänger" im Threadtitel beim Posten irgendwie überlesen. Insofern ist die ganze Diskussion OT. Vergesst doch einfach meinen Beitrag und redet ganz normal weiter. Vielleicht kann kingruedi sogar noch was reparieren.
-
Ein ebenfalls netter Fehler kommt, wenn man eine } vergisst.
Dann wird gemeldet: Unerwartetes Dateiende
... oder so ähnlich.
-
char i;
for (i=0; i<256; i++)
...
-
den sehe ich oft...
string hey (); int main() { cout<<hey; } string hey(){ return "hallo hey"; }