Fehler bei new []?!



  • also der fehler tritt genau dann auf, wenn ich den typ auf meine rationalen zahlen ändere. wenn t sowas wie float ist geht es ohne probleme. wobei ich die rationalen zahlen bzw float über eine typedef-bezeichnung einbinde, um halt im ganzen program schnell den typ anpassen zu können.
    also sowas wie

    typedef float t //damit gehts
    // alternativ, natürlich nicht beides gleichzeitig ;-)
    typedef crational_number t //damit nicht
    

    im rest wird dann immer mit t gearbeitet



  • aso, was ich vergessen hab zu erwähnen, vom C/C++ Optimierungscompiler gibts noch ne Fehlermeldung:

    Microsoft (R) C/C++-Optimierungscompiler hat ein Problem festgestellt und muss beendet werden.

    Vielleicht kann man da ja was einstellen, hab aber leider nichts gefunden und google hat mir diesbzgl auch nicht weiterhelfen können.


  • Mod

    In der Mehrzahl der ICE-Fälle ist ein Fehler im Quelltext der Grund, auf den der Compiler so nicht vorbereitet ist.
    Vermutlich hat das ganze mit dem new nichts zu tun, es tritt nur an dieser Stelle auf, weil dort die Templateklasse zum ersten mal instantiiert wird.
    Als erstes würde ich also prüfen, ob ein simples

    t foo;
    

    ebenfalls zu einem Fehler führt. Falls ja, kannst du versuchen, das Template schrittweise zu vereinfachen, bis der Fehler nicht mehr auftritt, um so die Quelle einzukreisen. Das Problem bei ICE ist ja, dass die Stelle, an der der Compiler aussteigt nahezu nichts mit dem zugrunde liegenden Problem zu tun hat.



  • also der fehler scheint in der rational_number klasse in kombination mit dem rational-template zu liegen, der aufbau ist im groben etwas so:

    template<class t>
    class rational
    {
    //...
    virtual void reduce_gcd(t &lhs, t &rhs) = 0;
    void simplify(); //ruft reduce_gcd auf
    //...
    }
    //...
    
    class rational_number : public rational<long>
    {
    //...
    void reduce_gcd(long &lhs, long &rhs){/*...*/};
    //...
    }
    

    ich bekomme dann die fehlermeldung:

    pure virtual function call
    

    an der stelle wo reduce_gcd() in der simplify-methode aufgerufen wird. allerdings sollte er doch die reduce_gcd()-methode von rational_number kennen und dann dort auch benutzen, oder sehe ich das falsch?



  • FreakyBKA schrieb:

    ich bekomme dann die fehlermeldung:

    pure virtual function call
    

    an der stelle wo reduce_gcd() in der simplify-methode aufgerufen wird.

    Du rufst nicht zufällig simplify aus dem rational-Konstruktor auf?



  • doch indirekt, nachdem der zähler und nenner gesetzt sind, soll ja quasi gekürzt werden (dafür ist die reduce_gcd()-methode da). wenn das falsch ist, dann wusste ich das nicht, würde micha ber interessieren, wie ich das dann beheben kann.



  • aso, der kennt die reduce_gcd-methode() von rational_number im rational-konstruktor ja noch gar nicht, oder?



  • FreakyBKA schrieb:

    aso, der kennt die reduce_gcd-methode() von rational_number im rational-konstruktor ja noch gar nicht, oder?

    Im rational-Konstruktor gibt es noch gar kein rational_number-Objekt. Man sollte in Konstruktoren und Destruktoren keine virtuellen Methoden aufrufen, bzw. man sollte wissen, was dann passiert.



  • ok, aber wie kann ich dann dafür sorge tragen, das nenner und zähler trotzdem gekürzt werden?



  • Muss reduce_gcd denn virtual sein?



  • naja, da rational ja eine template-klasse ist schon. den jeder typ kann eine andere methode erfordern den gcd zu entferen. bei long, int, etc. geht der euklidische algorithmus. wenn ich dann aber für t polynome mehrerer variablen einsetze dann brauche ich zB groebner-basen. bei polynomen in einer variable geht polynomdivision, aber das ist nur ein spezialfall von groebner-basen.

    rational soll quasi nur den kern aller rationalen objekte darstellen: zähler, nenner, grundoperationen und halt das man überall kürzen kann, sofern möglich.
    und für die einzelnen typen wird dann spezialisiert.



  • FreakyBKA schrieb:

    naja, da rational ja eine template-klasse ist schon. den jeder typ kann eine andere methode erfordern den gcd zu entferen.

    Gerade bei Templates bist du für solche Dinge nicht an Polymorphie durch Vererbung gebunden.

    Wie wäre es mit einem Policy-Templateparameter?



  • MFK schrieb:

    FreakyBKA schrieb:

    naja, da rational ja eine template-klasse ist schon. den jeder typ kann eine andere methode erfordern den gcd zu entferen.

    Gerade bei Templates bist du für solche Dinge nicht an Polymorphie durch Vererbung gebunden.
    Wie wäre es mit einem Policy-Templateparameter?

    Reicht es nicht völlig, daß gcd ein Template ist?



  • volkard schrieb:

    Reicht es nicht völlig, daß gcd ein Template ist?

    Reichen würden wohl schon ein paar Überladungen einer stinknormalen freien Funktion. Kommt halt drauf an, wieviele Möglichkeiten es da gibt, und ob man die geeignet zusammenfassen kann und ob für manche Typen mehr als eine Möglichkeit der Berechnung geeignet ist und ...



  • was ist unter einem policy-templateparameter zu verstehen? gebe ich da als zweites templateargument, dann eine klasse an die den gcd für zwei objekte des Typs t berechnet oder wie ist das zu verstehen.

    wie meinst du das mit dem gcd als template?



  • FreakyBKA schrieb:

    was ist unter einem policy-templateparameter zu verstehen? gebe ich da als zweites templateargument, dann eine klasse an die den gcd für zwei objekte des Typs t berechnet oder wie ist das zu verstehen.

    Genau so. Für jede Art, den Ggt zu berechnen, baust du ein Klassentemplate mit einer ganz bestimmten Methode, die die Berechnung durchführt. Diese Klassen müssen in keiner Vererbungsbeziehung stehen, die Schnittstelle muss nur "passen". Diese Klasse übergibst du als zweiten Templateparameter, ggf. auch mit einem Defaultwert, falls fast alle Typen dieselbe Methode benutzen, und nur einige wenige etwas anderes.

    FreakyBKA schrieb:

    wie meinst du das mit dem gcd als template?

    Implementiere die Ggt-Berechnung als freies Funktionstemplate, das du dann für bestimmte Templateparameter spezialisierst. Mit ein wenig Templatemetaprogrammierung lassen sich hier vielleicht bestimmte Typgruppen geschickt zusammenfassen.



  • also für template gcd würde das dann ungefähr so aussehen?

    template<class t>
    t gcd(t const &lhs, t const &rhs);
    //...
    
    long gcd<long>(long const &lhs, long const &rhs)
    {
    //euklidischer algorithmus
    }
    
    polynomial gcd<polynomial>(polynomial const &lhs, polynomial const &rhs)
    {
    //groebnerbasen benutzen
    }
    


  • FreakyBKA schrieb:

    also für template gcd würde das dann ungefähr so aussehen?

    Es bringt nicht viel, wenn du für jeden möglichen Typ einzeln spezialisierst. Das gleiche könntest du auch mit gewöhnlicher Überladung erreichen.

    Die Stärke des Template-Ansatzes liegt eher darin, dass du in Abhängigkeit von bestimmten Eigenschaften von t bestimmte Spezialisierungen "einschalten" kannst, Stichworte type_traits, enable_if, SFINAE.


Anmelden zum Antworten