Linker bzw. internal Compiler error
-
Da waren zwar endlose Fehler drin (Konvertierung von Funktionszeiger nach void*, Ptr:: in der Klasse, _ am Anfang (wobei das wohl gerade noch durchgehen dürfte)), aber dein eigentliches Problem konnte ich nicht feststellen...
http://ideone.com/XYDP5
Welchen Compiler nuzt du denn?
-
Was allerdings komisch ist, ist deine Fehlerbeschreibung, denn ein Linkerfehler ist etwas anderes als ein interner Compiler-fehler.
@cooky: Das mit dem _ am Anfang ist in diesem spezifischen Kontext nicht schlimm, da die Variable nur eine Eigenschaft einer Klasse und keine globale Variable ist.
-
Hacker schrieb:
@cooky: Das mit dem _ am Anfang ist in diesem spezifischen Kontext nicht schlimm, da die Variable nur eine Eigenschaft einer Klasse und keine globale Variable ist.
Lesen.. kannst du schon?
cooky451 schrieb:
_ am Anfang (wobei das wohl gerade noch durchgehen dürfte)
-
cooky451 schrieb:
Hacker schrieb:
@cooky: Das mit dem _ am Anfang ist in diesem spezifischen Kontext nicht schlimm, da die Variable nur eine Eigenschaft einer Klasse und keine globale Variable ist.
Lesen.. kannst du schon?
cooky451 schrieb:
_ am Anfang (wobei das wohl gerade noch durchgehen dürfte)
Nein. Ich kann nicht Lesen.
[/ironie]
[ernst]Ich hab das mit dem gerade noch..falsch verstanden.überlesen.
P.S.: Nein, kein Schluss-Tag
@TE: Das Ding ist eigentlich, dass im Zuweisungsoperator und im Default-Konstruktor zwei identische Sachen passieren.
-
Hacker schrieb:
Wieso benutzt du
std::wcout? Um Unicode -Zeichen darstellen zu können, brauchst du das sowieso nicht. Und das ist sehr sehr hässlich:reinterpret_cast<void(*)()>(myPtr.GetPtr())();Nimm (wenn es denn sein muss)
std::function/boost::function.Bei mir funktionieren übrigens beide Varianten reibungsfrei(also der Zuweisungsoperator und der Konstruktor).
Edit: Das alles oben ist sowieso sinnlos und hässlich. Was willst du machen?
Also ich weis nicht was an dem Funktionsaufruf hässlich sein soll. Dann schau dir mal die Implementierung von boost::function an. Das ist meiner Meinung nach hässlich. Mir geht es eigentlich nur darum eine Wrapper-Klasse um void* zu bauen.
cooky451 schrieb:
Da waren zwar endlose Fehler drin (Konvertierung von Funktionszeiger nach void*, Ptr:: in der Klasse, _ am Anfang (wobei das wohl gerade noch durchgehen dürfte)), aber dein eigentliches Problem konnte ich nicht feststellen...
http://ideone.com/XYDP5
Welchen Compiler nuzt du denn?Ich sehe da keine Fehler, bis auf das Ptr::. Wie gesagt habe das alles nur schnell zusammenkopiert. Mir wäre jedenfalls neu, dass die Konvertierung nach void* ein Fehler ist. Und ein _ vor (private) Membervariablen ist auch kein Problem sofern der nächste Buchstabe kleingeschrieben ist. Ist übrigens ein gängiger Codestyle.
Hacker schrieb:
Was allerdings komisch ist, ist deine Fehlerbeschreibung, denn ein Linkerfehler ist etwas anderes als ein interner Compiler-fehler.
Im eigentlichen Program bekomme ich einen LNK1257 gefolgt von einem C1001. Bei dem Code oben einen LNK2019 gefolgt von einem LNK1120.
Hacker schrieb:
@TE: Das Ding ist eigentlich, dass im Zuweisungsoperator und im Default-Konstruktor zwei identische Sachen passieren.
Ist das nicht so? Wie sollte der Zuweisungsoperator denn sonst ausschauen? Achso compiliert habe ich übrigens mit MS Visual Studio 2010.
-
@cooky451
Habe gerade den Code den du bei ideone gepostet hast getestet. Der läuft auch bei mir. Evtl. Stimmt da wirklich was mit dem void* nicht. Muss ich mir morgen mal in Ruhe anschauen. Habe da heute keinen Nerv mehr für.
-
Student83 schrieb:
Mir wäre jedenfalls neu, dass die Konvertierung nach void* ein Fehler ist.
Du darfst keine Objektzeiger in Funktionszeiger umwandeln. (Und auch nicht umgekehrt natürlich.) Es ist nur "conditionally supported". Einen Compilerfehler muss das aber nicht geben.
n3242 5.2.10 Reinterpret cast / 8 schrieb:
Converting a pointer to a function into a pointer to an object type or vice versa is conditionally-supported. The meaning of such a conversion is implementation-defined, except that if an implementation supports conversions in both directions, converting a prvalue of one type to the other type and back, possibly with different cv-qualification, shall yield the original pointer value.
Student83 schrieb:
Und ein _ vor (private) Membervariablen ist auch kein Problem sofern der nächste Buchstabe kleingeschrieben ist.
Das stimmt. Ob er jetzt private oder nicht ist, ist aber egal. Der Bezeichner darf nur nicht im globalen Namespace auftauchen.
Student83 schrieb:
Ist übrigens ein gängiger Codestyle.
Eher nicht. Es ist halt ziemlich nah an den reservierten Bezeichnern.
-
Student83 schrieb:
Also ich weis nicht was an dem Funktionsaufruf hässlich sein soll. Dann schau dir mal die Implementierung von boost::function an. Das ist meiner Meinung nach hässlich. Mir geht es eigentlich nur darum eine Wrapper-Klasse um void* zu bauen.
Weder ist boost::function schlecht, noch hat es einen entferntesten Sinn einen Wrapper um void* zu machen.
reinterpret_cast<void(*)()>(myPtr.GetPtr())();Was daran hässlich sein soll? Das ist doch jetzt ein Witz?
-
Also habe ich das jetzt richtig verstanden, dass der Compiler von Visual Studio 2010 wohl den Funktionszeiger nicht im void*-Zeiger speichern kann? Ich habe jetzt aber gelesen, dass mit dem C++11 Standard der reinterpret_cast garantiert wieder die gleiche Adresse zurückzuliefern. Habe desshalb mal Visual Studio 11 installiert und tatsächlich es funktioniert jetzt.
@cooky451
Das Problem mit dem Code von dir ist, dass du anstatt eines void-Pointers einen Funktionszeiger genommen hast. Mit diesem müsste ich mich aber auf eine Funktionsdefinition beschränken. Ich möchte aber, dass man die Parameter der Funktionen beliebig wählen kann. Das geht halt nur über einen void-Pointer.
-
Student83 schrieb:
Also habe ich das jetzt richtig verstanden, dass der Compiler von Visual Studio 2010 wohl den Funktionszeiger nicht im void*-Zeiger speichern kann? Ich habe jetzt aber gelesen, dass mit dem C++11 Standard der reinterpret_cast garantiert wieder die gleiche Adresse zurückzuliefern. Habe desshalb mal Visual Studio 11 installiert und tatsächlich es funktioniert jetzt.
@cooky451
Das Problem mit dem Code von dir ist, dass du anstatt eines void-Pointers einen Funktionszeiger genommen hast. Mit diesem müsste ich mich aber auf eine Funktionsdefinition beschränken. Ich möchte aber, dass man die Parameter der Funktionen beliebig wählen kann. Das geht halt nur über einen void-Pointer.Schon mal was von Templates gehört? Ganz tolle Sache, menJung.
Außerdem, welcher Code?
-
Der Code bei ideone: http://ideone.com/XYDP5
Irgendwie habe ich gewusst, dass jetzt jemand mit Templates kommt. Templates sind mal davon abgesehen, dass sie das Debugging erschweren bis unmöglich machen, oft schlechter zu lesen sind und die Trennung von definition und implementation (sagt man das so?) verhindern ganz nett. In diesem Fall für mich leider völlig unanwendbar, da alles dynamisch zu Laufzeit erzeugt wird und templates hier die Funktionalität nur einschränken würden.
Nur um mal ein Beispiel zu nennen: Ich nehme jetzt eine Template Klasse um die Funktionszeiger auch mit unterschiedlichen Paramtern speichern zu können (wobei das auch nur eingeschränkt funktioniert). Nun brauche ich aber auch eine Liste in der ich diese Template-Objekte speichern kann, da der Endanwender das Framework auch um eigene Funktionalität erweitern können soll. Also brauche ich eine Liste die mehr oder weniger Objekte beliebigen Typs aufnimmt. Dann kann ich aber auch gleich die Funktionszeiger als void* ablegen und habe mir dieses Templatekrebsgeschwür erspart.
-
Student83 schrieb:
Der Code bei ideone: http://ideone.com/XYDP5
Irgendwie habe ich gewusst, dass jetzt jemand mit Templates kommt. Templates sind mal davon abgesehen, dass sie das Debugging erschweren bis unmöglich machen, oft schlechter zu lesen sind und die Trennung von definition und implementation (sagt man das so?) verhindern ganz nett. In diesem Fall für mich leider völlig unanwendbar, da alles dynamisch zu Laufzeit erzeugt wird und templates hier die Funktionalität nur einschränken würden.
Nur um mal ein Beispiel zu nennen: Ich nehme jetzt eine Template Klasse um die Funktionszeiger auch mit unterschiedlichen Paramtern speichern zu können (wobei das auch nur eingeschränkt funktioniert). Nun brauche ich aber auch eine Liste in der ich diese Template-Objekte speichern kann, da der Endanwender das Framework auch um eigene Funktionalität erweitern können soll. Also brauche ich eine Liste die mehr oder weniger Objekte beliebigen Typs aufnimmt. Dann kann ich aber auch gleich die Funktionszeiger als void* ablegen und habe mir dieses Templatekrebsgeschwür erspart.Hä? Du willst eine Liste mit Funktionszeigern die alle auf verschiedene Funktions-typen zeigen?
Schlechtes Design, nichts weiter.
-
Man kann wenn es denn sein muss sowas verwenden (wenn ich dein Vorhaben verstanden hab):
#include <boost/any.hpp> #include <string> struct func { void operator()(int, std::string const&) {} }; int main() { std::vector<boost::any> vec; vec.push_back(func()); boost::any_cast<func>(vec[0])(5, "d"); }
-
Hacker schrieb:
Hä? Du willst eine Liste mit Funktionszeigern die alle auf verschiedene Funktions-typen zeigen?
Schlechtes Design, nichts weiter.
Im Prinzip ist das so. Klar in einem "abgeschlossenen" Programm, dass nicht erweitert werden können muss könnte ich jeweils für jeden Funktionstyp eine eigene Liste führen. Aber das Programm bzw. die Library muss eben auch nach dem Kompilieren noch für andere Funktionstypen erweiterbar sein. Das hat nichts mit schlechtem Design zu tun. Und selbst wenn doch. Was nützt mir ein super Design wenn die Library am Ende niemand oder nur eingeschränkt verwendet werden kann.
Hacker schrieb:
Man kann wenn es denn sein muss sowas verwenden (wenn ich dein Vorhaben verstanden hab):
#include <boost/any.hpp> #include <string> struct func { void operator()(int, std::string const&) {} }; int main() { std::vector<boost::any> vec; vec.push_back(func()); boost::any_cast<func>(vec[0])(5, "d"); }Im Prinzip trifft es das. Nur will ich wirklich kein boost::any und Konsorten verwenden (das ist in meinen Augen wirklich schlechtes Design), sondern stattdessen vereinfacht gesagt meine Ptr-Klasse die einen Wrapper um einen void-Pointer darstellt nehmen.
Alles was ich eigentlich noch wissen will ist, ob das mit C++11 jetzt garantiert ist, dass man einen Funktionszeiger (einer statischen Funktion) in einen void-Zeiger hinein und wieder zurück casten kann ohne, dass sich die Adresse verändert? Und ob das auch für unterschiedliche Plattformen gilt?
-
Und wie merkst du dir die Signatur der Funktion, damit spätere Aufrufe auch glatt laufen?
-
Die Ptr-Klasse ist ja nur die Basis auf der alles andere aufbaut. Jeder Handler hat eine virtuelle Invoke-Memberfunktion die das Aufrufen übernimmt.
-
Student83 schrieb:
Die Ptr-Klasse ist ja nur die Basis auf der alles andere aufbaut. Jeder Handler hat eine virtuelle Invoke-Memberfunktion die das Aufrufen übernimmt.
Das heißt, jeder handler hat seine eigene Funktion, oder? Denn "virtual" könnte sie nur sein, wenn sie die selbe Signatur wie die der Basisklasse hat - und somit ist der Vorteil einer gemeinsamen Basis wieder dahin.
Oder wo kommen die Argumente her? Speichert der spezialisierte Handler die irgendwo?
-
fiedelity schrieb:
Student83 schrieb:
Die Ptr-Klasse ist ja nur die Basis auf der alles andere aufbaut. Jeder Handler hat eine virtuelle Invoke-Memberfunktion die das Aufrufen übernimmt.
Das heißt, jeder handler hat seine eigene Funktion, oder? Denn "virtual" könnte sie nur sein, wenn sie die selbe Signatur wie die der Basisklasse hat - und somit ist der Vorteil einer gemeinsamen Basis wieder dahin.
Oder wo kommen die Argumente her? Speichert der spezialisierte Handler die irgendwo?Im Moment ist das so, aber ich habe ja erst angefangen das event-system zu entwickeln. Bin mir da bei ein paar Punkten noch unsicher. Zum Beispiel bei dem von dir genannten wie ich das mit dem Funktionsaufruf am besten löse. Wie würdest du das denn machen? Du scheinst dich ja mit dem Thema ein wenig auszukennen.
Mir geht es jetzt auch erstmal darum abzuchecken, ob das ganze vom Prinzip her überhaupt so funktioniert wie ich mir das vorgestellt habe. Was meinst du mit Argumenten? Die Funktionsparamter oder die Eventargumente?