Vortrags-Videos zu C++0x



  • Hallo,
    bei Googles "Education"-Programm gibt es einige interessante Vorträge über den neuen C++-Standard

    * New Features in the next C++ Standard von Lauwrence Crowl
    * C++0x Initialization Lists von Bjarne Stroustrup himself
    * Concepts Extending C++ Templates For Generic ProgrammingVon Douglas Gregor

    Das erste Video hab ich mir noch nicht angeschaut. Aber die anderen Videos sind sehr interessant. Initialization Lists ist definitiv ein nettes Feature. Aber Concepts sind der absolute Hammer.

    Concepts kann man übrigens schon heute ausprobieren mit dem ConceptGCC und der GCC 4.3 hat mittlerweile einen experimentellen C++0x-Modus.



  • Kann ich mir im Moment leider nicht ansehen.

    Was sind initialization lists?
    Was sind concepts?

    Bin gespannt!
    Falls jemand Lust hat, kann er es ja erklären.

    MfG





  • rüdiger schrieb:

    Aber Concepts sind der absolute Hammer.

    Habe mir auch garade nur die Concepts anschaut und ... Wow! Wirklich interessant.

    Edit: ] - verloren 🙂



  • Direkt mal ne Frage, habe nicht ConceptGCC drauf um das zu testen.

    Sagen wir mal ich habe eine Template-Funktion der ich MyClass [ T = MyClass ] übergebe und in dieser Funktion wird T a,b,c; c = a + b; gemacht. Und es gibt auch keinen op+(..MyClass..). Also meckert der Compiler.

    Nun setze ich ja als Anforderung Addable<T> an den Datentyp T. Aber eine Funktion op+ habe ich ja immer noch nicht. Kommt dann die selbe Fehlermeldung.



  • Nein, dann wird er dir etwas sagen als "Kein Konzept Addable<T> [ T = MyClass ] found" oä



  • Danke für die Links, sehr interessante Videos.

    Zum Inhalt:
    Concepts sind ganz praktisch, aber "der absolute Hammer" trifft es IMHO auch nicht so sehr.
    Sehr schön finde ich variadic template parameters und strong types, Konstruktoren-"Weiterleitung", constexpr und Initialisierungslisten.
    Die neue Notation für Rückgabewerte ist allerdings ziemlich nervig. Warum schon wieder eine neue, inkompatible, völlig abwegige Notation? 🙄
    Der Abschnitt über Garbage Collection irritiert mich ein wenig. Was soll "if the bits look like a pointer, they are" heißen - implementieren das GCs für C++ tatsächlich so? Das wird doch hoffentlich nicht in einem Standard-GC auftauchen?!?

    Ärgerlicherweise scheint es keine native Implementierung von Closures (aka Delegates) zu geben - nur diese ineffizienten, unübersichtlichen Funktionsobjekte. Dabei wäre es so einfach 😡
    Und warum gibt es keine VLAs? 😡



  • audacia schrieb:

    Ärgerlicherweise scheint es keine native Implementierung von Closures (aka Delegates) zu geben - nur diese ineffizienten, unübersichtlichen Funktionsobjekte.

    Funktionsobjekte sind überaus effizient. Und richtige Closures wären wegen des Stacks nicht so direkt machbar. "Delegates" sind ja auch nur Funktionsobjekte, wenn ich das richtig sehe und keine Closures.

    audacia schrieb:

    Und warum gibt es keine VLAs? 😡

    Nicht dringend benötigt und potenziell gefährlich. Keine Ahnung.



  • Mr. N schrieb:

    Funktionsobjekte sind überaus effizient.

    Was ist "überaus effizient"? Für mich ist es das hier:

    push this
    call [funcptr]
    

    Mr. N schrieb:

    Und richtige Closures wären wegen des Stacks nicht so direkt machbar.

    Wieso das?



  • audacia schrieb:

    Concepts sind ganz praktisch, aber "der absolute Hammer" trifft es IMHO auch nicht so sehr.

    Concepts werden wohl ziemlich viel für die Akzeptanz von Templates in der Nicht-Guru-Bevölkerung tun.

    Die neue Notation für Rückgabewerte ist allerdings ziemlich nervig. Warum schon wieder eine neue, inkompatible, völlig abwegige Notation? 🙄

    Hat er im Video erklärt. Das ist für Fälle, in denen der Rückgabetyp von den Parametern abhängt, die aber an der Stelle, wo er normalerweise steht, gar nicht sichtbar sind.

    Der Abschnitt über Garbage Collection irritiert mich ein wenig. Was soll "if the bits look like a pointer, they are" heißen - implementieren das GCs für C++ tatsächlich so? Das wird doch hoffentlich nicht in einem Standard-GC auftauchen?!?

    konservative GCs funktionieren nunmal so (Boehm z.B.). Viel besser gehts auch nicht, weil C++ ganz unten im Grunde eine schwach getypte Sprache ist. Man kann sogar konservative GCs aushebeln, wenn man gemein genug ist. Die Situation bessert sich ein bisschen, wenn man mit gc_strict verspricht, keine Schweinereien mit Pointern zu machen. Ist aber auch alles im Vortrag von Lawrence Crowl.



  • audacia schrieb:

    Mr. N schrieb:

    Funktionsobjekte sind überaus effizient.

    Was ist "überaus effizient"? Für mich ist es das hier:

    push this
    call [funcptr]
    

    Das wird dein Delegate nicht schaffen. Bzw. können Funktionsobjekte je nach Definition noch viel schneller sein.

    inc eax
    

    boost::function wiederum braucht wohl etwa die Zeit von 5 Funktionsaufrufen. Das ist nun wirklich vertretbar. Man sollte es natürlich nicht in inneren Schleifen aufrufen, aber das sollte man auch nicht mit Delegates...

    audacia schrieb:

    Mr. N schrieb:

    Und richtige Closures wären wegen des Stacks nicht so direkt machbar.

    Wieso das?

    Weil lokale Variablen im Closure gehalten werden müssten. Sie müssten also halb dem Closure und halb der Funktion gehören. Das erfordert wiederum eine weniger hardwarenahe Architektur als sie für C++ angepeilt wird.



  • Bashar schrieb:

    Hat er im Video erklärt. Das ist für Fälle, in denen der Rückgabetyp von den Parametern abhängt, die aber an der Stelle, wo er normalerweise steht, gar nicht sichtbar sind.

    Das habe ich schon verstanden. Aber nur, weil man den Compilerherstellern nicht zumuten will, den Rückgabetyp nach der Funktionssignatur zu verarbeiten!
    Außerdem sollte doch folgendes problemlos möglich sein:

    template <typename A, typename B>
    decltype (A() * B()) myFunction (A a, B b);
    

    Und nur für so eine Kleinigkeit eine neue Notation einzuführen, die mit einer nicht ganz unwichtigen Konvention bricht und je nach Gusto auch für jede beliebige Situation angewendet werden darf, finde ich unschön.

    Bashar schrieb:

    konservative GCs funktionieren nunmal so (Boehm z.B.). Viel besser gehts auch nicht, weil C++ ganz unten im Grunde eine schwach getypte Sprache ist. Man kann sogar konservative GCs aushebeln, wenn man gemein genug ist.

    Da scheine ich einiges in bezug auf GCs für C++ noch nicht verstanden zu haben.
    Wie das in Managed-Sprachen implementiert wird, kann ich mir vorstellen - da wird direkter Zeigerzugriff auf Heapspeicher ja in aller Regel unterbunden, so daß Objekte auf dem Heap nach Belieben herumgeschoben werden können.
    Wie aber soll das in C++ funktionieren, wo direkter Speicherzugriff möglich ist und beliebig viele Zeiger auf eine Speicherstelle zeigen können?

    Mr. N schrieb:

    Das wird dein Delegate nicht schaffen.

    Ein Delegate vielleicht nicht, aber ein Closure schon. Zumindest klappt das in Borlands Implementation einwandfrei.

    Außerdem, für einige Fälle mag boost::function vertretbar sein, aber es ist sowohl langsamer, als es sein könnte, als auch bläht es den Code gewaltig auf, da für jede Funktion, deren Adresse übergeben wird, eine Wrapperfunktion generiert wird. Daß C++ Closures nicht wie z.B. Delphi nativ unterstützt, ist ein Defizit der Sprache, für das boost::function lediglich ein Workaround mit den genannten Nachteilen darstellt.



  • audacia schrieb:

    Mr. N schrieb:

    Das wird dein Delegate nicht schaffen.

    Ein Delegate vielleicht nicht, aber ein Closure schon. Zumindest klappt das in Borlands Implementation einwandfrei.

    Delphi? Können die das wirklich? Javascript kanns, klar. Aber Delphi?

    audacia schrieb:

    Außerdem, für einige Fälle mag boost::function vertretbar sein, aber es ist sowohl langsamer, als es sein könnte, als auch bläht es den Code gewaltig auf, da für jede Funktion, deren Adresse übergeben wird, eine Wrapperfunktion generiert wird.

    Es wird ja niemand gezwungen, std::tr1::function genau so zu implementieren wie die Boost-Jungs.

    audacia schrieb:

    Daß C++ Closures nicht wie z.B. Delphi nativ unterstützt, ist ein Defizit der Sprache, für das boost::function lediglich ein Workaround mit den genannten Nachteilen darstellt.

    Closures passen nicht in das Runtime-Modell von C++. Ich fände es nicht richtig, das gesamte Runtime-Modell dafür umzuschmeißen und so jeden Funktionsaufruf langsamer zu machen.


  • Mod

    audacia schrieb:

    Bashar schrieb:

    Hat er im Video erklärt. Das ist für Fälle, in denen der Rückgabetyp von den Parametern abhängt, die aber an der Stelle, wo er normalerweise steht, gar nicht sichtbar sind.

    Das habe ich schon verstanden. Aber nur, weil man den Compilerherstellern nicht zumuten will, den Rückgabetyp nach der Funktionssignatur zu verarbeiten!
    Außerdem sollte doch folgendes problemlos möglich sein:

    template <typename A, typename B>
    decltype (A() * B()) myFunction (A a, B b);
    

    Und nur für so eine Kleinigkeit eine neue Notation einzuführen, die mit einer nicht ganz unwichtigen Konvention bricht und je nach Gusto auch für jede beliebige Situation angewendet werden darf, finde ich unschön.

    Das zeigt nur, dass du mit dieser Art 'Kleinigkeit' noch nie zu tun hattest. A()*B() ist durchaus etwas völlig anderes. Einerseits setzt es voraus, dass A und B defaultkonstruierbar sind. Zudem ist A() bzw. B() ein rvalue, a bzw. b sind aber lvalues (wenn A,B nicht gerade rvlaue-Referenzen sind... - gut, das könnte nicht durch Typdeduktion passieren) - gerade in Hinblick auf die dann existierenden rvalue-Referenzen (aber durchaus auch mit heutigen Sprachmitteln) kann das zu einem völlig anderen Ausdruck führen. Man könnte möglicherweise das ganze simulieren, wenn man Hilfsfunktionen einführt:

    template<typename T> T make();
    

    (wird nie definiert).
    wir könnten dann schreiben:

    template <typename A, typename B>
    decltype (make<A>() * make<B>()) myFunction (A a, B b);
    

    Aber wieder haben wir ein Problem hinsichtlich l- und r-value-Semantik, die wir nicht einfach dadurch lösen, dass wir make<A&>()*make<B&>() daraus machen. Ich behaupte nicht, dass es unlösbar schwierig ist, aber zumindest recht umständlich. Eine andere Form der Funktionsdeklaration erscheint da im Vergleich keineswegs abwegig.



  • camper schrieb:

    Das zeigt nur, dass du mit dieser Art 'Kleinigkeit' noch nie zu tun hattest. A()*B() ist durchaus etwas völlig anderes. Einerseits setzt es voraus, dass A und B defaultkonstruierbar sind. Zudem ist A() bzw. B() ein rvalue, a bzw. b sind aber lvalues (wenn A,B nicht gerade rvlaue-Referenzen sind... - gut, das könnte nicht durch Typdeduktion passieren) - gerade in Hinblick auf die dann existierenden rvalue-Referenzen (aber durchaus auch mit heutigen Sprachmitteln) kann das zu einem völlig anderen Ausdruck führen.

    Das leuchtet mir ein; danke für die Erläuterung.

    camper schrieb:

    Eine andere Form der Funktionsdeklaration erscheint da im Vergleich keineswegs abwegig.

    Was aber hindert die Standardkommission daran, einfach den Gültigkeitsbereich der in der Funktionssignatur deklarierten Parameter auf den Rückgabetyp auszuweiten und den Compilerherstellern das Aufschieben der Auswertung des Rückgabetyps zuzumuten?

    Mr. N schrieb:

    Delphi? Können die das wirklich? Javascript kanns, klar. Aber Delphi?

    Aber sicher. Was in Delphi als Funktionszeiger bezeichnet wird, sieht in C++Builder so aus:

    typedef void (__closure* myFunctionType) (void);
    

    Und es kann auf jede Memberfunktion jeder beliebigen Klasse zeigen, deren Funktionssignatur paßt. Also z.B.:

    #include <iostream>
    
    class MyClass
    {
    public:
        void myFunction (void)
        { std::cout << "hello from here!" << std::endl; }
    };
    
    typedef void (__closure* MyFunctionType) (void);
    
    int main(int argc, char* argv[])
    {
        MyClass mc;
        MyFunctionType mft = &mc.myFunction;
        mft ();
    }
    

    In Assembler:

    ;	int main(int argc, char* argv[])
     ;	
    	push      ebp
    	mov       ebp,esp
    	add       esp,-16
     ;	
     ;	{
     ;	    MyClass mc;
     ;	    myFunctionType mft = &mc.myFunction;
     ;	
    @1:
    	mov       dword ptr [ebp-16],offset @@MyClass@myFunction$qv
    	lea       eax,dword ptr [ebp-8]
    	mov       dword ptr [ebp-12],eax
     ;	
     ;	    mft ();
     ;	
    	push      dword ptr [ebp-12]
    	call      dword ptr [ebp-16]
    	pop       ecx
     ;	
     ;	    return 0;
     ;	
    	xor       eax,eax
     ;	
     ;	}
    

    audacia schrieb:

    Es wird ja niemand gezwungen, std::tr1::function genau so zu implementieren wie die Boost-Jungs.

    Gibt es bessere Alternativen?

    audacia schrieb:

    Closures passen nicht in das Runtime-Modell von C++. Ich fände es nicht richtig, das gesamte Runtime-Modell dafür umzuschmeißen und so jeden Funktionsaufruf langsamer zu machen.

    Wieso müßte man dafür deiner Vorstellung nach "das gesamte Runtime-Modell umschmeißen"?



  • audacia schrieb:

    Und es kann auf jede Memberfunktion jeder beliebigen Klasse zeigen, deren Funktionssignatur paßt.

    Das sind keine Closures! Zumindest nicht im eigentlichen Sinne. Eine Closure ist sowas:

    (let
      ((a 4))
      (lambda ()
        (begin
           (set! a (+ a 1))
           a)))
    
    ...
    
    (a)
    => 5
    (a)
    => 6
    (a)
    => 7
    

    audacia schrieb:

    Gibt es bessere Alternativen?

    Ein Compiler könnte mit ganz vielen Unterstrichen Tools für eine bessere Implementierung bereitstellten und diese nutzen.

    audacia schrieb:

    Wieso müßte man dafür deiner Vorstellung nach "das gesamte Runtime-Modell umschmeißen"?

    Wegen den in Closures gebundenen Variablen. Und damit meine ich nicht das this von deiner Member-Funktion.



  • audacia schrieb:

    Was aber hindert die Standardkommission daran, einfach den Gültigkeitsbereich der in der Funktionssignatur deklarierten Parameter auf den Rückgabetyp auszuweiten und den Compilerherstellern das Aufschieben der Auswertung des Rückgabetyps zuzumuten?

    LOL! Sehr witzig! 🤡 Genau das gleiche hatte man sich wohl 1998 gedacht, als man den Compiler-Herstellern "export" zumuten wollte. Weil es ja toll ist.

    Aber so läuft der Hase heute nicht mehr! Zum Glück! Heute sitzen nunmal die Compiler- und Library-Hersteller mit im Komitee und bedenken dieses mal im Voraus die Implementierungskosten und somit die eventuelle Komplexität. (siehe auch die Streichung der Special Math Library aus dem TR1, wegen zu hohen QA- und Implementierungs-Kosten) Besser ein Feature und Sonderwunsch fehlt in der ISO-Norm, anstatt in allen Compilern. Man hat vom export gelernt. Sonderlocken und Bimmelchen und Glöckchen werden wohl bedacht.



  • audacia schrieb:

    Bashar schrieb:

    konservative GCs funktionieren nunmal so (Boehm z.B.). Viel besser gehts auch nicht, weil C++ ganz unten im Grunde eine schwach getypte Sprache ist. Man kann sogar konservative GCs aushebeln, wenn man gemein genug ist.

    Da scheine ich einiges in bezug auf GCs für C++ noch nicht verstanden zu haben.
    Wie das in Managed-Sprachen implementiert wird, kann ich mir vorstellen - da wird direkter Zeigerzugriff auf Heapspeicher ja in aller Regel unterbunden, so daß Objekte auf dem Heap nach Belieben herumgeschoben werden können.
    Wie aber soll das in C++ funktionieren, wo direkter Speicherzugriff möglich ist und beliebig viele Zeiger auf eine Speicherstelle zeigen können?

    Speicherblöcke umherzuschieben gehört nicht unbedingt zu den Muss-Eigenschaften eines GCs.



  • rüdiger schrieb:

    Hallo,
    bei Googles "Education"-Programm gibt es einige interessante Vorträge über den neuen C++-Standard

    ich finde die google techtalks im allgemeinen ganz interessant und unterhaltsam...
    http://video.google.com/videosearch?q=Google+techtalks
    🙂



  • Mr. N schrieb:

    Das sind keine Closures! Zumindest nicht im eigentlichen Sinne.

    Dann scheinen wir uns mißverstanden zu haben. Was ich mit Closures meinte, habe ich oben beschrieben.

    Artchi schrieb:

    LOL! Sehr witzig! 🤡 Genau das gleiche hatte man sich wohl 1998 gedacht, als man den Compiler-Herstellern "export" zumuten wollte. Weil es ja toll ist.

    Aber so läuft der Hase heute nicht mehr! Zum Glück! Heute sitzen nunmal die Compiler- und Library-Hersteller mit im Komitee und bedenken dieses mal im Voraus die Implementierungskosten und somit die eventuelle Komplexität.

    Und da soll eine völlig neue Notation für den Rückgabetyp einfacher zu implementieren sein als das verzögerte Evaluieren des vorangestellten Rückgabetyps? Würde mich doch etwas wundern.

    Zudem ist export IMHO kein angemessener Vergleich. Daß export das konventionelle Compiler-Linker-Modell vor erhebliche Schwierigkeiten stellt, wird klar, wenn man sich ein wenig näher damit beschäftigt. Daß aber die Forderung, ein Typ dürfe erst nach den nachfolgenden Ausdruck ausgewertet werden, einen Compiler vor erhebliche Schwierigkeiten stellt, kann ich mir nicht vorstellen. Kann der Rückgabetyp innerhalb der Funktionssignatur benötigt werden (dann wäre aber auch die neue Notation hinfällig)? Ist es problematisch, den Gültigkeitsbereich der Funktionsparameter auf den Rückgabetyp auszuweiten - kann davon überhaupt ein anderer Gebrauch gemacht werden als mit decltype?

    Bashar schrieb:

    Speicherblöcke umherzuschieben gehört nicht unbedingt zu den Muss-Eigenschaften eines GCs.

    Mag sein, aber schränkt das nicht die Möglichkeiten eines GCs erheblich ein? Was macht dann ein GC für C++ anderes als ein auto_ptr, abgesehen davon, daß er den Speicher nicht beim Destruktoraufruf, sondern erst bei der Garbage-Collection freigibt? Und sorgen Mechanismen wie das Untersuchen des Speichers nach Daten, die wie Zeiger aussehen, nicht dafür, daß der GC sowohl unnötig Laufzeit verschwendet als auch eine nicht ganz unbeträchtliche Fehlerrate aufweist?


Anmelden zum Antworten