Template Funktionsaufruf- Interface
-
Hallo,
soweit bin ich bisher:
template<class T> static T GetValue(int x, string name, T value) { T t = T(); t.Parse(name); return t; }Der Compiler spuckt aus:
error C2228: Links von ".Parse" muss sich eine Klasse/Struktur/Union befinden.
Die Methode Parse habe ich abstrakt in einem "Interface" abgelegt. Die GetValue- Funktion wird nur von Klassen benutzt, die aus diesem Interface erben. Wo liegt aber der Fehler?
Grüße
-
Bitte ein komplettes Beispiel angeben, das den Fehler beinhaltet.
Ich kann Folgendes problemlos kompilieren:
template<class T> static T GetValue(int x, string name, T value) { T t = T(); t.Parse(name); return t; } struct Abstract { virtual void Parse(string) = 0; }; struct Concrete { virtual void Parse(string) {} }; int main() { GetValue(42, "foobar", Concrete()); }
-
Bei mir schaut es ähnlich aus, der Fehler ist aber trotzdem da:
class inter { public: virtual bool Parse(string text)=0; }; class Concrete : public inter { public: virtual bool Parse(string input) { return false; } }; int main { GetValue(42, "foobar", Concrete()); }
-
Kompiliert bei mir.
Kopiere die komplette Datei hierhin, die den Fehler verursacht. Nenne außerdem deine Compiler-Version.
-
Was meinst du mit komplette Datei?
Ich benutze Visual Studio 2008!
Kleine Unterschiede habe ich noch, die ich nicht für wichtig erachtet habe:
- Ich rufe GetValue nicht über die Main auf, sondern innerhalb einer Methode einer ganz anderen Klasse- Concrete erbt nicht direkt aus inter, sondern es gibt noch eine Klasse, die dazwischen liegt:
class HalbConcrete : public inter { }; class Concrete : public HalbConcrete { public: virtual bool Parse(string input) { return false; } };
-
neu_hier schrieb:
Kleine Unterschiede habe ich noch, die ich nicht für wichtig erachtet habe
Du solltest prüfen, ob der Code ohne die "kleinen Unterschiede" noch dasselbe Fehlverhalten zeigt.
-
neu_hier schrieb:
Was meinst du mit komplette Datei?
Du lässt die relevanten Informationen weg, denn das, was du bisher gezeigt hast, lässt sich problemlos mit VS 2008 kompilieren. Deshalb empfehle ich dir folgendes Vorgehen:
Erstelle ein Testprojekt (bzw. du hast wie ich ein Testprojekt, in dem du immer wieder kleine Codestücke z. B. aus dem Forum ausprobieren kannst). Kopiere die relevanten Dateien aus dem Originalprojekt in das Testprojekt. Entferne solange irrelevanten Code wie sich die Fehlermeldungen nicht ändern. Wenn du durch diese Vorgehensweise den Fehler noch nicht selbst gefunden hast, kanst du im Forum den Code posten, der im Testprojekt übrigbleibt.
-
Ich habe du vermutlich relevante Information gefunden:
template<class T> static T GetValue(TiXmlElement* x, string name, T value) { T t = T(); t.Parsetest(name); return t; }Ich benutze TinyXml und übergebe eine "TiXmlElement" in dem GetValue. Sobald ich aber einen "int" stattdessen übergebe, verschwindet der Fehler...
Wie der Zufall so will enthält TinyXml ebenfalls eine Methode "Parse", also habe ich die im Interface benutzte Methode zu Parsetest geändert. Leider ohne Ergebnis. Der Fehler besteht weiterhin.Danach habe ich einfach mal einen Pointer zu dem TiXmlElement übergeben -> der Fehler verschwindet! Aber warum? An anderer Stelle übergebe ich erfolgreich ein TiXmlElement (u.a. auch in eine template Klasse). Nun befürchte ich, dass mich der Fehler irgendwann heimsuchen wird. Und mit irgendwann meine ich den Zeitpunkt, an dem ich dieses Problem völlig vergessen habe und keine Ahnung habe woher es kommt

-
neu_hier schrieb:
Ich benutze TinyXml und übergebe eine "TiXmlElement" in dem GetValue.
Für x oder value?
neu_hier schrieb:
Danach habe ich einfach mal einen Pointer zu dem TiXmlElement übergeben
Für x oder value?
Den Parameter x benutzt deine Beispielfunktion gar nicht. Das Verhalten hängt vom Typ von value ab. Zu dem hast du aber bisher nichts gesagt.
Zeig doch bitte endlich mal den Aufruf, oder ein vollständiges Beispielprogramm, das den Fehler reproduziert. Dein Beispielcode und deine Erklärungen sind absolut unzureichend für eine Diagnose.
-
MFK schrieb:
Für x oder value?
In beiden Fällen für x
MFK schrieb:
Den Parameter x benutzt deine Beispielfunktion gar nicht.
Das macht es eben um so lustiger! Ich benutze den Parameter x nicht (habe ich testweise ausgeklammert) und trotzdem werden Fehler ausgespuckt, wenn der Parameter x kein Pointer ist!
Ich fasse am Besten nochmal die Programmschnippsel zusammen, auf die ich das ganze runtergebrochen habe:
class inter { public: virtual bool Parse(string text)=0; }; class HalbConcrete : public inter { public: virtual bool Parse(string input) { return false; } }; class Concrete : public HalbConcrete { }; int main(TiXmlElement elem) { if (&elem == NULL) { return 0; } GetValue(&elem, "foobar", Concrete()); // je nach template (siehe unten) //GetValue(elem, "foobar", Concrete()); }Mit diesem template läuft es:
template<class T> static T GetValue(TiXmlElement* x, string name, T value) { T t = T(); t.Parse(name); return t; }Mit diesem template nicht:
template<class T> static T GetValue(TiXmlElement x, string name, T value) { T t = T(); t.Parse(name); return t; }
-
neu_hier schrieb:
Ich fasse am Besten nochmal die Programmschnippsel zusammen, auf die ich das ganze runtergebrochen habe:
Das bringt überhaupt nichts, wenn du nicht prüfst, ob dein heruntergebrochenes Programmschnipsel dasselbe Fehlverhalten aufweist. Und das tut es nicht. Kommt das bei dir irgendwie nicht an?
Folgendes Programm kompiliert ohne Fehler:
#include <string> using namespace std; class TiXmlElement { public: void Parse(string) {} }; template<class T> static T GetValue(TiXmlElement x, string name, T value) { T t = T(); t.Parse(name); return t; } class inter { public: virtual bool Parse(string text)=0; }; class HalbConcrete : public inter { public: virtual bool Parse(string input) { return false; } }; class Concrete : public HalbConcrete { }; int main() { TiXmlElement elem; GetValue(elem, "foobar", Concrete()); }
-
Ich tippe darauf, daß es mit "TiXmlElement" im Originalcode nicht kompiliert, weil höchstwahrscheinlich beim Template-Code die Klasse nur als Vorwärtsreferenz bekannt gemacht wurde und nicht mittels "include <tinyxml.h>" bekannt ist.
-
MFK schrieb:
Das bringt überhaupt nichts, wenn du nicht prüfst, ob dein heruntergebrochenes Programmschnipsel dasselbe Fehlverhalten aufweist. Und das tut es nicht. Kommt das bei dir irgendwie nicht an?
Ich habe mein Programm genau auf das heruntergebrochen, was ich gepostet habe und der Fehler tritt bei mir auf! Der einzige Unterschied zu deinem Programmcode ist nur, dass ich die Bibliotheken "tinyxml.h" und "tinystr.h" einbinde anstatt TiXmlElement zu definieren.
Th69 schrieb:
Ich tippe darauf, daß es mit "TiXmlElement" im Originalcode nicht kompiliert, weil höchstwahrscheinlich beim Template-Code die Klasse nur als Vorwärtsreferenz bekannt gemacht wurde und nicht mittels "include <tinyxml.h>" bekannt ist.
Ich hatte es als Vorwärtsreferenz bekannt gemacht. Nun habe ich aber die Bibliotheken eingebunden -> gleicher Fehler
-
neu_hier schrieb:
Der einzige Unterschied zu deinem Programmcode ist nur, dass ich die Bibliotheken "tinyxml.h" und "tinystr.h" einbinde anstatt TiXmlElement zu definieren.
Das kann ja schon mal nicht sein, weil mein Code mit dem echten TiXmlElement nicht funktioniert, da die Klasse keinen Defaultkonstruktor hat.
Aber dann eben so: Letzte Version von TinyXML runtergeladen, die betroffenen Header eingebunden:
#include <string> #include "tinystr.h" #include "tinyxml.h" using namespace std; template<class T> static T GetValue(TiXmlElement x, string name, T value) { T t = T(); t.Parse(name); return t; } class inter { public: virtual bool Parse(string text)=0; }; class HalbConcrete : public inter { public: virtual bool Parse(string input) { return false; } }; class Concrete : public HalbConcrete { }; int main() { TiXmlElement elem("foo"); GetValue(elem, "foobar", Concrete()); }=> Kompiliert, linkt natürlich nicht.
Bei dir nicht?
Welcher Compiler?
Welche TinyXML-Version ?
-
Compiler ist Visual Studio 2008 SP1.
TinyXml Version 2.5.5!
-
neu_hier schrieb:
TinyXml Version 2.5.5!
Das ist die Versionnummer, die bei 2.6.1 (warum auch immer) in der changes.txt steht.
Ich hab's gerade mal mit Visual Studio 2008 SP1 probiert -> Kompiliert.
Kannst du bitte mal ein neues Konsolenanwendungsprojekt anlegen, die Header und meinen Code reinkopieren und es ausprobieren?