C++09 (Teil 1) - Ein Überblick: Sprachfeatures



  • Hallo, queer_boy! Meinen Respekt für die Arbeit, die du in den Artikel gesteckt hast.

    Hier sind ein paar Anregungen und Verbesserungsvorschläge:

    Zu Variadischen Templates: Man könnte noch erwähnen, dass der eingebaute "sizeof..."-operator eigentlich ein template a la count_args<>::value erspart. Das 3. Codebeispiel scheint einen copy/paste Fehler zu enthalten. Statt

    template <class T, class ...Args>
    T* make_new (Args&& ...args)
    {
       //expandiert automatisch richtig:
       return new T( *new Args(static_cast<Args&&>(args)) ...);
    }
    

    müsste es doch eigentlich heißen

    template <class T, class ...Args>
    T* make_new (Args&& ...args)
    {
       //expandiert automatisch richtig:
       return new T(static_cast<Args&&>(args)...);
    }
    

    oder nicht?

    Zu Rvalue-Referenzen: Das Beispiel "Optimierungen von std::string" wird nach den neuen Regeln nicht kompilieren und ist auch nicht wirklich im Sinne der Spracherweiterung. Das Zurückgeben von Referenzen birgt die Gefahr von "baumelnden Referenzen". Nach den neuen Regeln binden Rvalue-Referenzen auch keine Lvalues mehr. Aber das, was Du zurückgiebst sind Lvalue-Ausdrücke. In neueren Beispielen findet man soetwas:

    string operator+(string && a, string const& b)
    {
      a += b;
      return move(a);
    }
    

    Das move() ist hier notwendig, weil 'a' ein Referenz-Parameter ist, der wie ein Lvalue-Ausdruck behandelt wird. (Das move() ist aber bei lokalen Variablen überflüssig und sollte vermieden werden, weil es die NRV-Optimierung des Compilers umgehen könnte).

    Neue Funktions-Syntax: Ich glaube nicht, dass Deine typedefs und die Deklaration des Arrays a korrekt sind. Der Deklarator sitzt da an der falschen Stelle:

    typedef (auto (int) -> int) F; // Falsch
    typedef auto F(int) -> int;    // Richtig
    

    Lambdas: Soweit ich weiß, fehlt da bei dem einen oder anderen Lambda-Ausdruck die Return-Anweisung und/oder ein Semikolon. Einige Klammern sind auch falsch. Beispiel:

    int i = [](int x, int y) (x + y) (42,23);       // Falsch
    int i = [](int x, int y) {return x+y;} (42,23); // Richtig
    

    Das war's erstmal von mir.

    Gruß,
    Sebastian



  • Ich probiere gerade die Beta1 vom VS 2010 aus, mal eine Frage: Kann man die Lambda-Funktionen eigentlich "ordentlich" übergeben? Mit VS klappt sowas:

    template<typename T>
    void whatever( T calc )
    {
    	std::cout << calc( 10 ) << std::endl;
    }
    
    int main()
    {
        whatever( [](int x)->int {return x*2;} );
    }
    

    Würde gerne den Typ angeben (also zumindest Parameter-Anzahl), konnte dazu im Artikel aber nichts finden.



  • Kleine frage noch.
    Ich glaube das das auhc noch dazu gehört^^

    In C hat man ja die endungen C & H benutzt für Quellcode daten und header
    in C++ wurden folgende mit eingeeführt: CPP & HPP.
    Jedoch habe ich auch CXX und HXX gefunden, haben diese ihren ursprung aus dem C++0x Standard oder wo kommen diese her?

    Mfg Wikinger75!



  • Badestrand schrieb:

    Ich probiere gerade die Beta1 vom VS 2010 aus, mal eine Frage: Kann man die Lambda-Funktionen eigentlich "ordentlich" übergeben? Mit VS klappt sowas:

    template<typename T>
    void whatever( T calc )
    {
    	std::cout << calc( 10 ) << std::endl;
    }
    
    int main()
    {
        whatever( [](int x)->int {return x*2;} );
    }
    

    Würde gerne den Typ angeben (also zumindest Parameter-Anzahl), konnte dazu im Artikel aber nichts finden.

    Ein Lambda-Ausdruck generiert ein Objekt eines einzigartigen aber anonymen Typs. Die Template-Parameter-Herleiting des Compilers ist das einzige, was Dich direkt ein Lambdaobjekt halten lässt. Das schlißt auch "auto" mit ein:

    int main()
    {
        auto f = [](int x)->int {return x*2;};
        whatever( f );
    }
    

    Du kannst aber so ein Funktionsobjekt mit Hilfe der "Type Erasure"-Technik in einem anderen Funktionsobjekt kapseln. Dazu ist das Bibliotheks-Feature "std::function" gedacht:

    #include <functional>
    
    void whatever( std::function<int(int)> calc )
    {
    	std::cout << calc( 10 ) << std::endl;
    }
    
    int main()
    {
        whatever( [](int x)->int {return x*2;} );
    }
    

    Hier wird das Lambda-Objekt implizit zu einem std::function<int(int)> objekt konvertiert. Hinter dem Vorhang läuft das mit Laufzeit-Polymorphie (abstrakte Basis-Klasse mit virtuellen Funktionen). Man kann aber davon ausgehen, dass eine qualitativ gute Implementierung von std::function sehr effizient bei "kleinen" Funktionsobjekten funktioniert. In diesem Fall hat Dein Lambda-Objekt gar keinen "Zustand". Es sollte also von der "small-function-optimization" profitieren. Bei großen Funktionsobjekten muss man hier auf den Freispeicher ausweichen.

    Bis vor kurzem gab es noch eine andere Möglichkeit, Lambda-Objekte, die entweder gar nichts einfangen oder alle Variablen im umliegenden Geltungsbereich per Referenz fangen: reference_closure<>. Dieser Ansatz war aber nicht viel besser als std::function. Er wurde deswegen wieder aus dem Entwurf genommen.

    Gruß,
    Sebastian



  • Wikinger75 schrieb:

    Kleine frage noch.
    In C hat man ja die endungen C & H benutzt für Quellcode daten und header
    in C++ wurden folgende mit eingeeführt: CPP & HPP.
    Jedoch habe ich auch CXX und HXX gefunden, haben diese ihren ursprung aus dem C++0x Standard oder wo kommen diese her?

    Das sind lediglich Konventionen. Die Endungen der Dateinamen sind nicht standartisiert. CXX und HXX gabs vor C++0x auch schon. 🙂

    Gruß,
    Sebastian



  • Sebastian Pizer schrieb:

    Du kannst aber so ein Funktionsobjekt mit Hilfe der "Type Erasure"-Technik in einem anderen Funktionsobjekt kapseln. Dazu ist das Bibliotheks-Feature "std::function" gedacht

    Perfekt, danke! Und danke auch für die Erklärungen drumherum. Das Komitee hat wirklich verflucht gute Arbeit geleistet 👍



  • Ein paar neue Prinzipien finde ich gut, aber dass viel zu viele meiner Meinung nach sinnlos. Ich weiß nicht, was ich insgesamt davon halten soll.



  • Ist vermutlich schon bekannt. Aber der Vollständigkeit halber: Concepts wurden aus dem Draft wieder entfernt und werden kein Bestandteil von C++0x werden.

    Bjarne Stroustrup erklärt warum http://www.ddj.com/cpp/218600111

    Und hier noch ein Artikel von Doug Gregor dazu: http://cpp-next.com/archive/2009/08/what-happened-in-frankfurt/





  • Keep working ,impressive job!


Anmelden zum Antworten