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



  • Ich habe eine Frage zu den variadic templates. Wenn ich als template-Argumente eine Liste von ints habe, möchte ich ja auch auf die einzelnen Einträge zugreifen können. Geht also sowas wie:

    template <int ...x> struct foo
    { 
      static const int bar[sizeof...(x)] = { x... };
      const int operator[](const int i)
      {
        return bar[i];
      }
    };
    
    int main()
    { 
      foo<0, 0, 0> f;
      return f[1];
    }
    

    Oder gibt es eine andere Möglichkeit? 😕



  • Purrrfect schrieb:

    Ich habe eine Frage zu den variadic templates. Wenn ich als template-Argumente eine Liste von ints habe, möchte ich ja auch auf die einzelnen Einträge zugreifen können. Geht also sowas wie:

    template <int ...x> struct foo
    { 
      static const int bar[sizeof...(x)] = { x... };
      const int operator[](const int i)
      {
        return bar[i];
      }
    };
    
    int main()
    { 
      foo<0, 0, 0> f;
      return f[1];
    }
    

    Oder gibt es eine andere Möglichkeit? 😕

    Früher war afaik der Syntax [].[index] im Gespräch - afaik ist der aber nicht durchgekommen.
    Deine Möglichkeit wär' wohl möglich - schöner wär aber was mit constexpr...



  • queer_boy schrieb:

    das war david vandevoorde (der sich mit templates ja wirklich gut auskennt), was genaueres weiß ich auch nicht, aber das könnte man ja einmal in comp.lang.c++.moderated besprechen.

    Please forgive me for responding in English: I don't write German.

    Here is my position on C++0x concepts. It's an interesting feature, but it is currently unimplemented. There is a partial implementation (ConceptGCC) of an earlier specification, but what was voted in the working paper is significantly different. That brings about a fair number of risks, in my opinion:
    - Potentially breaking significant existing code (because of library changes) in ways we are not aware of.
    - Potentially being programmer-unfriendly (i.e., I worry that I might more often than not find writing a constrained template to be an unpleasant affair).
    - Potentially have an excessive number of semantic holes (i.e., having to significantly revise/extend the specification long after the language standard has been published).
    - Potentially being excessively expensive to implement.

    Note that I'm not saying that "C++0x concepts are a bad idea"; instead I say "There is -- in my opinion -- insufficient evidence that the current incarnation of C++0x concepts is a well-executed good idea".

    Part of the problem here is that we're dealing with a very large feature that is essentially added "all at once" to the language. (Compare that to the original templates, which were added to the language by bits and pieces, and then eventually standardized after we had industrial experience with most of it.)

    Hopefully, my worries will turn out to be unfounded.

    Daveed



  • 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