primitives instanceof



  • GorbGorb schrieb:

    Naja, das Resultat ist ja das Gleiche.

    Da wäre ich mir nicht so sicher. Wenn static_cast geht, ziehe es vor.

    GorbGorb schrieb:

    Ich bin mir sehr sicher, dass das mit meiner Version deutlich schneller geht (hab grade im gcc getestet, und so wie es aussieht braucht eine typeid-comparison etwa 5x so lang wie ein int Vergleich). Vielleicht arbeite ich das noch weiter aus und schicks den boost-Leuten mal, hoffentlich wird was draus.

    Vielleicht solltest du zuerst ein paar Bugs beseitigen (Kopiersemantik). Und etwas ausführlicher und in verschiedenen Situationen auf verschiedenen Compilern testen. Und dann gibts noch heimtückischere Fallen, z.B. die fehlende Threadsicherheit beim Zugriff auf static -Objekte. Generell würde ich vielleicht eher zuerst in der Boost-Mailingliste eine Diskussion starten 😉

    Ausserdem könntest du möglicherweise die Performance weiter optimieren, indem du auf die AnyTypeWrapper -Klasse verzichtest und stattdessen direkt void* und Funktionszeiger verwendest. Macht auch den Code kürzer.

    Aber die Idee mit automatisch vergebenen Integer-IDs für Typen ist echt gut. Ich muss damit unbedingt mal herumexperimentieren. Ich habe nämlich das Problem, dass meine Dynamic-Dispatchers elend langsam sind, und der Grossteil der Zeit bei std::type_info -Vergleichen verloren geht.



  • Nexus schrieb:

    Ich habe nämlich das Problem, dass meine Dynamic-Dispatchers elend langsam sind, und der Grossteil der Zeit bei std::type_info -Vergleichen verloren geht.

    Alexandrescu hat einen O(1) Dispatcher, wenn ich mich recht erinnere 🙂



  • 314159265358979 schrieb:

    Alexandrescu hat einen O(1) Dispatcher, wenn ich mich recht erinnere 🙂

    Ja, aber der ist intrusiv. So einen baue ich vielleicht auch eines Tages, aber ich brauche nebenbei auch eine Version, die ohne Veränderung bestehender Klassen auskommt.

    Aber ich sehe gerade, eins habe ich nicht bedacht: Um eine virtuelle Funktion oder RTTI komme ich nicht herum, falls ich zur Laufzeit die Typ-ID eines Objekts herausfinden will. Die Integer-Lösung bringt mir hier also nicht allzu viel. Aber vielleicht anderswo... 😉



  • Klassen in der Skriptsprache sind nicht geplant. Ich meinte im Startpost, dass ich beliebige C++-Klassen im Container speichern können will.
    Es werden also nur feste Typen erlaubt sein.

    @ 314159265358979:

    Type Erasure

    Wo ist dabei der Vorteil gegenüber boost::any?

    boost::variadic

    Ich habe die which()-Methode übersehen. Mit der wäre das natürlich möglich.
    Anderes Problem: Dieser Artikel sagt mir, dass Visual Studio noch keine Variadic Templates unterstüzt.
    Außerdem sehe ich immer noch nicht den Zusammenhang zum Visitor Pattern.

    @ wxSkip: Ich verstehe nicht, was das mit dem Problem zu tun hat? Oder beziehst du das auf Klassen + Member?

    @ Ethon: Unions erlauben aber keine nicht-PODs.

    @ krümelkacker: Ich habe nie von beliebig vielen Typen geredet, sondern nur von beliebigen Typen 😉



  • Zum Visitor Pattern: Boost lässt dich mit apply_visitor einen Visitor auf die Variant anwenden. Nehmen wir an, in deiner Sprache steht der Ausdruck "a + b". Je nachdem, welchen Typ deine Variablen haben, kann das verschiedenes bedeuten. Zuerst stellst du fest, dass a z.B. ein string ist. Jetzt lässt du einen visitor<string> über b laufen. Ist b ebenfalls ein string, dann kannst du diesen direkt zurückgeben. Ist b ein int, dann kannst du ihn implizit konvertieren und zurückgeben. Ist b etwas anderes, könntest du eine Exception werfen. Mit dem Visitor pattern könnte man hier also Konvertierungen umsetzen.

    Was Type Erasure angeht hatte ich ähnliche Gedanken, aber mitterweile denke ich, dass boost::variant am geeignetsten ist.



  • @Wurst: Ich weiß immer noch nicht genau, was du machen willst. Willst du für die Typen in deiner Skriptsprache genau die gleichen C++-Typen verwenden. Oder willst du die unbekannten C++-Typen nur gleichartig in deinem Interpreter verwenden? Es ist ein Zeichen von gutem Design, wenn du Polymorphie Typecasts und Identifizierungen vorziehst. Wenn du mit variant/any/... einfach nur Variablen repräsentieren willst, kannst du das mit Instanzen eigener Typklassen machen, die von einer (abstrakten) Basisklasse abgeleitet werden. Dann kannst du in vielen Fällen die Member der Klassen selbst die Operation spezifisch für den bestimmten Typ durchführen lassen.



  • @ 314159265358979: Macht Sinn. Ich hatte vor, Funktionen zum Konvertieren zu schreiben, aber so ist es einfacher.

    @ wxSkip: Ich möchte in meiner Skriptsprache die Typen bool, int, double, char, string und eventuell noch andere haben. Diese sollen vom Interpreter mit den gleichnamigen C++-Typen gespeichert werden.
    Da ich noch nicht so weit mit der Planung des Codes bin, bin ich mir nicht sicher, ob mit Polymorphie alles zu regeln wäre.

    Da MSVC keine Variadic Templates unterstützt wird es wohl dennoch auf boost::any oder Polymorphie + enum mit dem Variablentyp hinauslaufen. Außer, Visual Studio 2011 kommt in den nächsten paar Wochen :p

    Weitere Vorschläge sehe ich natürlich gern, aber trotzdem bedanke ich mich schon für die bereits aufgekommenen.



  • Auch wenn das jetzt sicher nicht das beste Design ist, manchmal ist einfach besser (wurde hier ja auch schonmal vorgeschlagen):

    enum Type
    {
      TYPE_CHAR,
      TYPE_INT,
      ...
    };
    
    struct Variable
    {
      Type type;
      union
      {
        char char_value;
        int int_value;
        ...
      } value;
    };
    


  • Wurst schrieb:

    Ich möchte in meiner Skriptsprache die Typen bool, int, double, char, string und eventuell noch andere haben.

    Das schreit nach Polymorphie, denn mit einer enum/union/any-Konstruktion darfst du jedes Mal alle Casting-Versuche um einen Typ ergänzen. Und die Möglichkeit eines Einsatzes von Polymorphie deutet auch auf einen logischen Sprachaufbau deiner Scriptsprache hin.



  • Wurst schrieb:

    Klassen in der Skriptsprache sind nicht geplant. Ich meinte im Startpost, dass ich beliebige C++-Klassen im Container speichern können will.

    Du meinst sicherlich "Objekte von beliebigen Typen". Aber wozu?

    Wurst schrieb:

    @ krümelkacker: Ich habe nie von beliebig vielen Typen geredet, sondern nur von beliebigen Typen 😉

    Da man Typen nicht "speichert", sondern höchstens "unterstützt", macht das keinen Unterschied.



  • @ dot:
    union will aber keine strings haben.

    @ wxSkip:
    Logisch? Eigenlich nicht.
    Welche Typen ich letztendlich einbauen werde, werde ich mir überlegen, bevor ich mit dem Programmieren anfange. "ergänzen" muss ich also nicht 🙂

    @ krümelkacker:

    Du meinst sicherlich "Objekte von beliebigen Typen". Aber wozu?

    Ja, stimmt, ich meinte Objekte. Wozu, steht doch im Startpost.

    Da man Typen nicht "speichert", sondern höchstens "unterstützt", macht das keinen Unterschied.

    Darum nennt man ihn also den "Arbeitsunterstützer"? 😉



  • Wurst schrieb:

    @ dot:
    union will aber keine strings haben.

    Aber std::string*. Und wie schon erwähnt kannst du in eine variant std::string reinwerfen.



  • Wurst schrieb:

    @ dot:
    union will aber keine strings haben.

    In C++0x wär das kein Problem 😉



  • Wurst schrieb:

    Da man Typen nicht "speichert", sondern höchstens "unterstützt", macht das keinen Unterschied.

    Darum nennt man ihn also den "Arbeitsunterstützer"? 😉

    Du verwechselst wohl wieder Typen und Objekte.



  • Wenn es sich um eine dynamische typisierte Skriptsprache handelt, warum schaust du dir nicht mal eine Implementation an? Zu empfehlen sind Lua oder Scheme in verschiedenen Versionen. Fuer gewoehnlich wird mit union + type tag gearbeitet. Darueber hinaus gibt es kleinere Optimierungen bezueglich einfacher Datentypen wie Byte, Double oder Integer.



  • @ 314159265358979:
    Mit einem Pointer wäre der Gebrauch aber viel schwerer.
    Wie gesagt, boost::variant kann ich nicht verwenden, selbst wenn ich will.

    @ dot:
    Ich will C++0x aber nur verwenden, wenn es gar nicht anders geht, z.B. um boost::variant zu benutzen. Auf halbgare Unterstützung von den Compilern habe ich keine Lust, da warte ich lieber, bis es zum Standard wird.

    @ krümelkacker:
    Ein Objekt wird im Arbeitsspeicher gespeichert. Wieso sollte ich da was verwechseln?

    @ knivil:
    Wenn ich einen einfachen Interpreter finde, werde ich das mal machen.
    Ich entwickle die Sprache aber nur zu "Demonstrationszwecken", nicht, um damit wirklich viel zu programmieren. Garbage Collector, OOP oder sonstwas im Source Code würden mir also nicht helfen, sondern mir eher das Verständis erschweren.



  • Wurst schrieb:

    Mit einem Pointer wäre der Gebrauch aber viel schwerer.

    Nö. Du musst nur die großen 3 richtig definieren.

    Wurst schrieb:

    Wie gesagt, boost::variant kann ich nicht verwenden, selbst wenn ich will.

    Warum denn?



  • Wurst schrieb:

    Ich will C++0x aber nur verwenden, wenn es gar nicht anders geht, z.B. um boost::variant zu benutzen.

    Boost.Variant geht auch auf C++03-Compilern. Zumindest bis zu einem bestimmten Limit (10) an Typparametern auch direkt, danach brauchst du eine Typliste.



  • @ 314159265358979:

    Nö. Du musst nur die großen 3 richtig definieren.

    Die vergess ich immer 😛

    Warum denn?

    Sagte ich doch, weil MSVC keine Variadic Templates unterstüzt.
    Wenn es so ist, wie ipsec sagt, stimmt das natürlich nicht mehr.



  • Wurst schrieb:

    Die vergess ich immer 😛

    Musst du doch nur bei deiner Variablenklasse, das wirst du doch schaffen.

    Wurst schrieb:

    Sagte ich doch, weil MSVC keine Variadic Templates unterstüzt.
    Wenn es so ist, wie ipsec sagt, stimmt das natürlich nicht mehr.

    Natürlich stimmt das, warum sollte er dich anlügen?


Anmelden zum Antworten