ist ein fehler in diesem programm?



  • ja! erste geposteten funktion ist ein wenig modifiziert. Es wird nur der Rest aller Zahlen bis \|n (Wurzel n), für n gleich zu testender wert, getestet. Bei einer Vielzahl an Werten kann dadurch so mach eine Sekunde eingespart werden.

    Bei der zweiten Variante weiß ich nicht ob es ihm weiterhilft. Aber vlt. hilft es jemand anderem weiter. Die Zeiteinsparung spricht jedenfalls (meiner Meinung nach) für sich! In dem zweiten Beispiel wird nämlich die komplette Berechnung ob es sich um eine Zufallszahl handelt zu Zeiten des Kompilierens ausgeführt



  • Bei mir funktioniert alles. Die einzige Fehlermeldung die ich bekomme ist folgende 😉

    main.cpp:42:1: Warnung: Kein Newline am Dateiende

    Wie rufst du die Metafunktion auf? Natürlich lässt sich die Metafunktion nur mit einem konstanten ausdruck aufrufen, also nicht mit einer Laufvariablen einer Schleife.



  • lucky_tux schrieb:

    Bei mir funktioniert alles. Die einzige Fehlermeldung die ich bekomme ist folgende 😉

    main.cpp:42:1: Warnung: Kein Newline am Dateiende

    Wie rufst du die Metafunktion auf? Natürlich lässt sich die Metafunktion nur mit einem konstanten ausdruck aufrufen, also nicht mit einer Laufvariablen einer Schleife.

    Wenn ich einfach nur deinen Beispiel-Code compilieren will, tritt das Problem auf. Ich hab gcc 3.4.4.

    mfg.



  • #include <iostream>
    
    template <bool Val, typename True, typename False>
    struct if_ : public True
    {
    };
    
    template <typename True, typename False>
    struct if_<false, True, False> : public False
    {
    };
    
    template <bool Val>
    struct BoolType
    {
        static const bool value = Val;
    };
    
    template <unsigned int N, int i, bool Val>
    struct isprime_helper : public
                             if_<(i*i > N)
                               , BoolType<true>
                               , if_<(N % i)
                                    , isprime_helper<N, i + 1, Val>
                                    , BoolType<false>
                                    >
                               >
    {};
    
    template <unsigned int N>
    struct isprime
    {
        static const bool value = isprime_helper<N, 2, false>::value;
    };
    
    template<>
    struct isprime<1>
    {
        static const bool value = false;
    };
    
    int main()
    {
      std::cout << isprime<5>::value << std::endl;
      std::cout << isprime<100>::value << std::endl;
    }
    

    So funktionierts.

    Spacelord schrieb:

    Hast du toll gemacht......aber glaubst du dass das Ben1990 irgendwie weiter bringt?

    Dann passt es doch sehr gut zum Rest des Threads 🙄



  • lucky_tux schrieb:

    ... oder das ganze als Metaprogramm ...

    Hm... 🙄 ich weiss nicht, ich weiss nicht:

    Statt den Standard zu zitieren zitiere ich zur Abwechslung mal Comeau C++:

    "ComeauTest.c", line 17: error: identifier "sqrt" is undefined
        static const int sqrt_n = static_cast<int>(sqrt(n));
                                                   ^
    
    "ComeauTest.c", line 17: error: function call is not allowed in a constant expression
        static const int sqrt_n = static_cast<int>(sqrt(n));
                                                   ^
    
    "ComeauTest.c", line 23: error: specializing class "isprime<1>" without "template<>"
              syntax is nonstandard
      struct isprime<1>
             ^
    

    Viel mehr muss man dazu nicht sagen. 👎



  • #include <iostream>
    using namespace std;
    
    int main()
    {
        cout << "2 ist eine Primzahl\n";
        cout << "3 ist eine Primzahl\n";
        cout << "5 ist eine Primzahl\n";
        // ...
    }
    

    Die Geschwindigkeit spricht für sich 🙄



  • template <unsigned int N, int i, bool Val> 
     struct isprime_helper : public 
                              if_<(i*i > N) 
                                , BoolType<true> 
                                , if_<(N % i) 
                                     , isprime_helper<N, i + 1, Val> 
                                     , BoolType<false> 
                                     > 
                                > 
     {};
    

    @.filmor:

    Sehr geschickt gelöst das Problem mit sqrt. Wenigstens einer der die Funktionalität der Metaprogrammierung nicht grundlos unterschätzt.

    @Antiposer:

    Ich finde es schade, dass sich so wenige Leute mit der Metaprogrammierung auseinandersetzen. Vorallendingen Anfänger sind von dem neuen, noch recht unerforschten (Bezug auf Libraries wie die MPL) Konzepten der Metaprogrammierung abgeschreckt. Vorallendingen in wissenschaftlichen Applikationen würde ich diese Art der Programmierung nie unterschätzen. Die MPL z.B. etliche Möglichkeiten für mathematische Berechnungen, Type Traits und Manipulation, uvm.



  • lucky_tux schrieb:

    Vorallendingen Anfänger sind von dem neuen, noch recht unerforschten (Bezug auf Libraries wie die MPL) Konzepten der Metaprogrammierung abgeschreckt.

    Ich denk eher, dass die Syntax und die Programmlogik noch zu schwer für nen Anfänger sind.



  • lucky_tux schrieb:

    @Antiposer:
    Ich finde es schade, dass sich so wenige Leute mit der Metaprogrammierung auseinandersetzen. Vorallendingen Anfänger sind von dem neuen, noch recht unerforschten (Bezug auf Libraries wie die MPL) Konzepten der Metaprogrammierung abgeschreckt. Vorallendingen in wissenschaftlichen Applikationen würde ich diese Art der Programmierung nie unterschätzen. Die MPL z.B. etliche Möglichkeiten für mathematische Berechnungen, Type Traits und Manipulation, uvm.

    Keine Frage, da hast Du die Intention meines Kommentares auch total misverstanden. In der Tat kann man damit feine Sachen machen, aber zwei Dinge sollte man nicht vergessen: Es ist deutlich komplizierter es richtig zu machen (wie schön gezeigt wurde) und daher nicht einsteigerfreundlich (und verwirrt den Fragesteller unter Garantie mehr als es ihm hilft) und es reduziert die Portabilität, da Metaprogrammierung halt schwerer auf verschiedene Plattformen portiert werden kann. Im speziellen Fall der Primzahlenbestimmung geht zudem die Anzahl der Situationen, in denen man zur Compilezeit den Primzahlentest machen kann (weil man da den zu testenden Wert schon kennt), grob gegen Null.

    Metaprogrammierung hat viele Vorteile, aber auch manche Nachteile, und wer beruflich in grossen Projekten zu tun hat wird als einen starken Nachteil die langen Übersetzungszeiten empfinden, die nicht unerwähnt bleiben sollten. Ich kenne aus leidiger beruflicher Erfahung genug Projekte die man an einem Tag kaum oder garnicht mehr bauen kann, bei grösserflächigerem Metaprogrammierungs-Einsatz würde diese Zeit noch deutlich schlimmer. Ein echter Kostenfaktor. Wenn die Primzahl aber wirklich statisch getestet werden müsste, könnte man das immernoch in die Initialisierungsphase der Anwendung ziehen und sich das Ergebnis merken, wäre genauso Flott zur eigentlichen Laufzeit, nicht wirklich gross im Code und schnellst zu übersetzen.

    So bleibt ein von Dir möglicherweise als Aufruf zur Würdigung von Metaprogrammierung gedachtes Posting halt erstmal als wenig hilfreich und zudem falsch bezogen auf das Topic (das nicht nach geschickter Primzahlenerzeugung fragt, sondern nach Fehlern in einem konkreten Listing aus einem Buch) der schale Geschmack eines möglichen Poser-Postings. Wenn ich das wirklich missverstanden habe, so tut mir das leid. Aber speziell nach der Antwort der Art "bei mir tut es aber" musste ich einfach davon ausgehen, weil das kein Argument für konformen Code ist und das sollte man wissen, wenn man mit Metaprogammierung erfolgreich arbeiten will. 😉

    Also nix für ungut, ich mag Metaprogrammierung auch! 🤡



  • Ich find's trotzdem gut dass er den Metacode noch gepostet hat. Da ich gerade am lernen von templates bin, ist es gut ein paar Beispiele zu sehen. Besonders das if_ von .filmor find ich klasse! Wär ich gar nicht auf die Idee gekommen.

    mfg.



  • @Antiposer:

    Entweder man ist offen für neue Dinge oder man ist es nicht. Man kann niemanden zwingen die Metaprogrammierung einzusetzen (beruflich sieht das manchmal vlt. ein wenig anders aus), aber ich fände es gut wenn sich mehr Programmierer über neue Konzepte am laufenden halten würden und der Code dementsprechend performanter wird.

    Du Argumentierst mit zu langen Kompilierzeiten... Die Berechnungen finden so oder so statt. Nur muss auch bedacht werden, dass bei der Verwendung der Metaprogrammierung die Berechnung nur einmal beim kompilieren stattfindet, bei der Alternative hingegen bei jeder Ausführung des Programms. Bedeutet Einbuße von Performance.



  • lucky_tux schrieb:

    Du Argumentierst mit zu langen Kompilierzeiten... Die Berechnungen finden so oder so statt.

    Bei der Meta-Programmierung sind die Berechnungen aber wesentlich aufwändiger. BTW konnte man mich noch nicht davon überzeugen, weil ich noch keinen sinnvollen Einsatzzweck davon gesehen habe.



  • Bei der Meta-Programmierung sind die Berechnungen aber wesentlich aufwändiger

    Inwiefern sollen die Berechnungen deutlich aufwändiger sein? Nenne bitte ein Beispiel, da ich mir im Moment nichts unter dieser Aussage vorstellen kann...

    Habe mir den Quelltext meines Entwufs des Metaprogramms noch mal angesehen. Die Unterschiedlichen Probleme mit sqrt sind darauf zurückzuführen, dass einige Compiler das Ergebnis von sqrt nicht wegoptimieren und als Ausdruck betrachten, sondern den Wert zu Laufzeiten berechnen. Bei der zweiten Variante des Metaprogramms bestehen keine derartigen Probleme; das Programm ist voll funktionsfähig und ist meines erachtens plattformunabhängig.



  • Zum einen für den Entwickler aufwändiger, da er nur wenige Operationen zur Verfügung hat und zum anderen aufwändiger für den Compiler, weil er sehr viele Template-Instanzierungen machen muss.



  • Ich finde nicht das es mehr Aufwand für den Programmierer ist, wenn entsprechende Bibliotheken bereitstehen. Die MPL (Boost) zum Beispiel bietet Möglichkeiten, die die Verwendung der Metaprogrammierung deutlich vereinfachen.

    Natürlich, sollte man den "Zufuß Weg" wählen, ist das Schreiben äquivalenten Codes deutlich komplexer und redundanter (... und wenn man die Metafunktion if_ zum 100sten male gecodet hat...) .

    Ich finde wir sollten die Diskusion damit auch beenden, da wir anscheinend keine wirklich neuen Argumente finden und es sich hier in gewisser Weise auch um eine Frage der Überzeugung handelt. Wenn du die ganzen Berechnungen in die Laufzeit deines Programms "packen" willst, dann wird dich niemand daran hindern. 😉



  • lucky_tux schrieb:

    Bei der Meta-Programmierung sind die Berechnungen aber wesentlich aufwändiger

    Inwiefern sollen die Berechnungen deutlich aufwändiger sein? Nenne bitte ein Beispiel, da ich mir im Moment nichts unter dieser Aussage vorstellen kann...

    🙄 Ist doch klar, die Auswertung der Metaprogrammierungs-Implementation findet natürlich quasi geskriptet statt und u.a. wegen der eingeschränkten Ausdrucksböglichkeiten (insbesondere in einer Weise die möglichst viele Compiler verstehen) sind die Zwischenergebnisse hochkomplexe Typinformationen mit langen Symbolnamen und Manglings deren Symboltabellenpflege natürlich deutlich komplexer ist als die Ausführung eines regulären Primzahlentests.

    Daneben ist als kleine Randbemerkung noch zu beachten, das der Standard nur die Unterstützung von min. 17 Templateschachtelungen vorschreibt, da kommt man mit allzu komplexen Beispielen natürlich schnell drüber hinaus und bewegt sich damit im Implementationsabhängigen Bereich. Und wer könnte schon im Vorhinein jedem Metaprogramm ansehen wie tief das wohl schachteln mag...

    Generell werden auf allen mir bekannten Compilern templatelastigere Sourcen spürbar langsamer übersetzt und das kann mit steigender Komplexität leicht zu einem merhfachen der Compiletime führen.

    lucky_tux schrieb:

    Habe mir den Quelltext meines Entwufs des Metaprogramms noch mal angesehen. Die Unterschiedlichen Probleme mit sqrt sind darauf zurückzuführen, dass einige Compiler das Ergebnis von sqrt nicht wegoptimieren und als Ausdruck betrachten, sondern den Wert zu Laufzeiten berechnen.

    ⚠ Womit sie auch absolut recht haben, denn Funktionsaufrufe sind halt nicht Teil von constant expressions. Ich zitiere hier einfach doch mal den Standard, ➡ aus [5.19] Constant expressions: "In particular, except in sizeof expressions, functions, class objects, pointers, or references shall not be used, and assignment, increment, decrement, function-call, or comma operators shall not be used."

    Es ist also keine Optimierung, sondern einfach nicht Standardkonform. Der Standard sagt nicht etwa das diese Optimierung optional ist, er verbietet schlicht dieses Feature. Es mag sein, das Compiler das trotzdem zur Zeit können, aber es muß immer damit gerechnet werden, das dies nicht bestehen bleibt und im Zuge weiterer Umsetzung des Standards rausfliegt.

    Man kann natürlich fragen warum das so definiert ist und es misbilligen, aber wenn wir jetzt anfangen zu empfehlen "vergiss den Standard, wenn es baut ist es richtig", erweisen wir den Leuten einen Bärendienst.

    lucky_tux schrieb:

    Bei der zweiten Variante des Metaprogramms bestehen keine derartigen Probleme; das Programm ist voll funktionsfähig und ist meines erachtens plattformunabhängig.

    😋 Ja, die sqrt-lose Variante ist auf hinreichend modernen Compilern gut benutzbar und zudem Standardkonform, was auch für eine Verbesserung der Benutzbarkeit mit neueren Compilerversionen spricht. Die Übersetzungszeitproblemeatik bleibt zwar, aber natürlich kann es Situationen geben, wo die nicht relevant ist. Man sollte sie halt nur in die Entscheidungsfindung mit einbeziehen.


Anmelden zum Antworten