vergesst C++ ...



  • volkard schrieb:

    maximAL schrieb:

    äh, wo kommt der triplet-typ jetzt her?

    ist allgemeinbildung...

    ja, schon klar 😉
    ändert aber nichts dran, dass C++ die rückgabetypen nicht vollständig selbst ermitteln kann (davon, dass man nichtmal was zurückgeben muss ganz zu schweigen *brrr*)



  • volkard schrieb:

    O'Rakl schrieb:

    womit ich nicht in Abrede stelle, daß C für resourcen-kritische und hardware-nahe Aufgaben erste Wahl ist,

    erstens falsch und zweitens irrelevat.

    Bezüglich "hardwarenah": Irrelevant? Ja. Falsch? Nein, eher unvollständig. C _und_ C++ (O.K. gibt noch andere) sind bestens dafür geeignet. Die Frage ist, ob der/die Schreiber nun die Vorteile von OOP nutzen wollen oder nicht. Viele (die meisten) wollen das halt nicht. Oft scheitert es halt auch daran, dass für die Zielarchitektur keine (guten) C++ Compiler verfügbar sind.



  • maximAL schrieb:

    ändert aber nichts dran, dass C++ die rückgabetypen nicht vollständig selbst ermitteln kann

    kann es nicht? welchen typ wird createTriple(2, 5.0f, "hoi!") wohl haben?
    nur unpraktisch ist, daß man typen vor variablen schreiben muß. aber das wird geändert, hoffe ich.

    auto t=createTriple(2, 5.0f, "hoi!");
    

    und wenn nicht, geh ich von c++ weg. dann hat's einfach keinen sinn mehr mit diesem standardisierungskomitee.



  • volkard schrieb:

    maximAL schrieb:

    ändert aber nichts dran, dass C++ die rückgabetypen nicht vollständig selbst ermitteln kann

    kann es nicht? welchen typ wird createTriple(2, 5.0f, "hoi!") wohl haben?

    trotzdem muss du in der definition angeben, dass es ein triple zurückgibt - und du brauchst erstmal den entsprechenden rückgabetyp. gut, das mag in diesem beispiel nicht so schlimm erscheinen, aber auf ein komplettes programm bezogen macht das imho schon was aus.



  • volkard schrieb:

    und wenn nicht, geh ich von c++ weg. dann hat's einfach keinen sinn mehr mit diesem standardisierungskomitee.

    Dann würde ich weggehen, das werden die nie im Leben ändern. Geh zu C#, für C# 3.0 sind implizite Typen geplant. 😉
    btw. finde ich nicht, dass Destruktoren GC ersetzen. Destruktoren sind toll für deterministische Destruktion von Objekten, was man in jeder Sprache braucht und in jeder Sprache, die hier angesprochen wurde, auch hat. Deterministische Destruktion mit einer automatischen Speicherverwaltung zu vergleichen ist wie Äpfel mit Birnen zu vergleichen.

    Bei komplizierten Zusammenhängen kann man nicht immer leicht den idealen Zeitpunkt bestimmen, wann ein Objekt freizugeben ist. Nimm doch mal nen Graphen mit vielen Knoten der ständig dabei ist, sich irgendwie zu verändern. Wie wir beide wissen, ist Referenzzählung hier nicht zuverlässig.
    Was ist jetzt der ideale Zeitpunkt für die Freigabe eines Knotens? Klar geht es. Niemand behauptet, dass automatische Speicherverwaltung notwendig ist. Aber angenehm ist sie, effizient ist sie (meistens) und sie lässt sich nicht durch Destruktoren oder Referenzzählung ersetzen. Die Antwort ist, wenn man einen GC hat: "Ist mir egal, was der ideale Zeitpunkt wäre". Die Antwort ist, wenn man keinen GC hat, kompliziert, weil man den idealen Zeitpunkt schlicht nicht verpassen oder ihm zuvor kommen darf. Ich verstehe nicht, was du immer gegen garbage collection hast. Das ist wirklich ein Feature, was man meistens ohne Bedenken anwenden und einem die Arbeit wirklich erleichtern kann.



  • maximAL schrieb:

    trotzdem muss du in der definition angeben, dass es ein triple zurückgibt -

    ultra-lästig. mit typeof vom gcc kann ich die variablen ja schon machen, aber rückgabetypen in der funktionsdefintion gehen o nicht. ich hoffe auf den nächsten standard.



  • @O'Rakl
    Weisst du, du bist ein echter Troll. Immer wieder die selben und sinnlosen Argumente. Wie wäre es, wenn du meine Beiträge mal ganz durchliest, anstatt einzelne Passagen zu zitieren und mir dann die Worte im Mund umzudrehen. Nur mal so als Bsp.

    O'Rakl schrieb:

    Hauptsache, C/C++, hm ?

    Wo hab ich denn sowas gesagt? Du solltest echt Lesen lernen, vielleicht hast du deshalb auch nie C++ begriffen. Lesen heisst nicht nur, aneinander gereihte Buchstaben zu wiederholen, sondern diese auch zu verstehen. 😉

    groovemaster schrieb:

    Selbst C++ Programmierer in diesem Forum betonen immer wieder, dass man die Sprache nehmen sollte, die für den Zweck angemessen ist. [...] Und wenn Python für ein Projekt die bessere Wahl ist, dann wäre ich dumm, dies nicht zu nehmen.

    O'Rakl schrieb:

    Nun ist es aber so, daß C++ mangels eingebauter Datenstrukturen und aufgrund des auf C aufgepropften Objekt-Modells viele sehr einfache Dinge (wie L=["a",1.0]) sehr kompliziert macht, auch wenn sie mit hohem Aufwand und unter Verwendung
    äußerst raffinierter externer Bibliotheken (STL,boost,...) möglich sind.

    Gähn... (Anm.: seltsamerweise musste ich tatsächlich gähnen, als ich das gelesen habe - kein Witz)

    O'Rakl schrieb:

    Meinst Du wirklich ?

    Dir fehlt echt das Verständnis Zusammenhänge zu verstehen. Mein Statement bezog sich auf maximAL's tuple Beispiel.

    O'Rakl schrieb:

    Zum Einen erfordert höhere programmtechnische Eleganz
    und Kürze eine gewisse Abstraktion in Form eines dynamischen Typkonzepts
    und Garbage Collection

    Erstmal nö. Ich wüsste nicht, warum GC zu mehr Eleganz und Abstraktion führen sollte. Beschäftige dich mal mit scope-basiertem Ressourcenmanagement, dann verstehst du vielleicht, warum C++ keinen GC braucht. Was das dynamische Typkonzept betrifft, da hab ich erstmal grundsätzlich nichts dagegen, aber nur, wenn es nicht auf Kosten des statischen Typsystems implementiert ist. Und da hab ich so meine Zweifel, dass beide Typsysteme unter einem Dach zu mehr Eleganz führen.

    O'Rakl schrieb:

    , zum Andern ist C++ doch schon groß und kompliziert
    genug

    Das kommt natürlich immer auf den Standpunkt an. Für Leute wie dich, die davon überhaupt keine Ahnung haben, mag das so erscheinen. Erfahrene C++ Programmierer werden an der Sprache nicht mehr viel finden, was wirklich kompliziert ist. Da bietet die Verwendung der richtigen Algorithmen und Design Patterns schon deutlich mehr Herausforderung.

    @maximAL
    Wenn ich dich richtig verstanden habe, willst du sowas hier:

    auto add_multiply_divide(int a, int b)
    {
        return make_tuple(a+b, a*b, double(a)/double(b));
    }
    // bzw.
    tuple add_multiply_divide(int a, int b)
    {
        return make_tuple(a+b, a*b, double(a)/double(b));
    }
    

    Sowas geht aber nicht, denn was soll der Compiler denn hier machen?

    auto add_multiply_divide(int a, int b);
    // bzw.
    tuple add_multiply_divide(int a, int b);
    

    Im ersten Fall kann er den Typ überhaupt nicht herleiten, ausser auto beschreibt etwas wie VB's Variant. Und im zweiten Fall weiss er zwar, dass es ein tuple ist. Er weiss aber nicht, wie es aussieht. Ausser es wird dynamisch gehandelt. Beides hat aber mit einem statischen Typsystem nichts zu tun. Und wer jetzt behauptet, dass Funktionsdeklarationen überflüssig sind, bekommt eins auf die Nuss. Gerade für Schnittstellen, zB über dynamische Bibliotheken, ist das äusserst effektiv und universell einsetzbar. Selbst in anderen Sprachen.

    ->Sovok<- schrieb:

    und wie gesagt in der praxis sind zahlen und strings im selben container selten nötig

    Das würde ich zwar nicht behaupten, für die Praxis ist das Beispiel trotzdem irrelevant, da man die Elemente des Containers eher dynamisch einliest (zB aus einem Textfile oder einer Datenbank), anstatt diese fest vorzugeben.



  • groovemaster schrieb:

    Sowas geht aber nicht, denn was soll der Compiler denn hier machen?

    auto add_multiply_divide(int a, int b);
    // bzw.
    tuple add_multiply_divide(int a, int b);
    

    error 4711: auto kann nicht in deklarition ohne definition benutzt werden
    error 4712: basta.

    ich will das aber haben tun.
    ich schreib ja jetzt schon lieber

    #define AUTO(name,init) typeof(init) name(init)
    AUTO(in,openFileForRead("in.txt"));
    AUTO(out,openFileForWrite("out.txt"));
    

    als

    FileReader in(...);
    FileReader out(...);
    

    und weil ich schon lange vergessen haben will, wie die typen wirklich heißen, wenn ich nur die erzeugende funktion kenne, muß es dann auch weitergehen mit

    auto openFileForReadByNumber(int nr){
       strstream name;
       name<<nr<<".txt";
       return openFileForRead(name.c_str());
    }
    

    daß der compiler dann auch noch dafür sorgen sollte, daß das ding nicht zwingend static linkage haben muß, gehört halt auch noch dazu. mit export?



  • groovemaster schrieb:

    Im ersten Fall kann er den Typ überhaupt nicht herleiten, ausser auto beschreibt etwas wie VB's Variant. Und im zweiten Fall weiss er zwar, dass es ein tuple ist. Er weiss aber nicht, wie es aussieht.

    also ehrlichgesagt versteh ich das problem jetzt nicht so ganz.
    nochmal ganz kurz, wie das typsystem in meinem beispiel funzt: die funktion ist generisch und erst mit dem aufruf der parameter wird der rückgabetyp bestimmt. desweiteren muss man den rückgabetyp nirgends explizit hinschreiben (auch keinen "platzhalter"), sondern es wird überprüft, welchen typ die funktion tatsächlich zurückgibt. dürfte in C++ schwierig sein, denn da muss man im prinzip gar nichts zurückgeben - selbst wenn ein rückgabewert definiert ist 😉
    quasi: würde in meiner C++ funktion return MeinInteger; stehen, dann wüsste der compiler, was ich will.

    ps: das soll übrigens kein aufruf sein, diese funktionalität irgendwie nachzubauen oder den standard dementsprechend zu erweitern. ich sage nur, dass es leider so nicht geht, aber imho in eine wirklich moderne hochsprache gehört.



  • maximAL schrieb:

    dürfte in C++ schwierig sein, denn da muss man im prinzip gar nichts zurückgeben - selbst wenn ein rückgabewert definiert ist 😉

    da wirft schon wieder einer halbwissend der armen sprache c++ was vor, was in c so ist. also mein compiler erlaubt ir nicht int f(){};.



  • volkard schrieb:

    maximAL schrieb:

    dürfte in C++ schwierig sein, denn da muss man im prinzip gar nichts zurückgeben - selbst wenn ein rückgabewert definiert ist 😉

    da wirft schon wieder einer halbwissend der armen sprache c++ was vor, was in c so ist. also mein compiler erlaubt ir nicht int f(){};.

    also mein minGW frisst das ohne weiteres. ok, mit -Wall gibts zumindest ne warnung...



  • maximAL schrieb:

    also mein minGW frisst das ohne weiteres. ok, mit -Wall gibts zumindest ne warnung...

    Mein gcc gibt nen Error raus.



  • Werfen wir einfach einen genaueren Blick darauf.

    // nicht erlaubt
    int foo() {
    }
    
    // erlaubt
    int foo(bool something) {
    	if( something )
    		return 5;
    }
    

    ➡ affig



  • maximAL schrieb:

    also mein minGW frisst das ohne weiteres. ok, mit -Wall gibts zumindest ne warnung...

    Mein msvc gibt nen error raus. Nur weil main() keinen return erfordert, heißt das nicht, das es bei funktionen und methoden auch so ist.

    Sehr schön, das die OpenSource-Compiler so standardkonform sind.



  • Artchi schrieb:

    Sehr schön, das die OpenSource-Compiler so standardkonform sind.

    tja, theorie und praxis, was? 😉
    ok, die leere funktion ist verboten. was ist aber mit dem if-kontrukt (laut standard)?



  • volkard schrieb:

    error 4711: auto kann nicht in deklarition ohne definition benutzt werden
    error 4712: basta.

    LOL. Schön das du wenigstens das ganze mit Humor nimmst.

    maximAL schrieb:

    quasi: würde in meiner C++ funktion return MeinInteger; stehen, dann wüsste der compiler, was ich will.

    Mir ist schon klar, was du willst. Aber nochmal, ein Compiler sieht bei einer Deklaration kein return MeinInteger;. Wie soll er also den Rückgabetyp bzw. -wert herleiten?

    @Optimizer
    Mal schauen, was der Standard dazu sagt.

    Flowing off the end of a function is equivalent to a return with no value; this results in undefined behavior in a value-returning function.

    Und wenn ich mir die Asm Listings beim MSC anschau, das kommt das ziemlich gut hin. Imo alles korrekt, wenn ein Compiler beim zweiten Beipiel nur eine Warnung bringt.



  • Ich habe ja nie behauptet, dass mein Compiler das gegen den Standard erlaubt. Ganz im Gegenteil bezog sich der Begriff "affig" auf die Regel, dass es gleichzeitig mindestens ein return-Statement geben muss, andererseits muss nicht jeder Kontrollpfad ein return-Statement enthalten. So eine inkonsequente Regel bringt meines Erachtens keinen erkennbaren Vorteil, mit Warnung zwar auch keinen Nachteil, aber naja.



  • Hoppla, schon wieder Feierabend... und wieder die C++-Arbeit eines Wochenendes
    mit durchwachten Nächten an einem halben Vormittag erledigt. 🙂
    Danke, Python.



  • Optimizer schrieb:

    So eine inkonsequente Regel bringt meines Erachtens keinen erkennbaren Vorteil, mit Warnung zwar auch keinen Nachteil, aber naja.

    naja, geschichte.
    natürlich haben wir alle -Wall und -Werror an. daß es eigentlich erlaubt ist, daß eine funktion affig ist, ignoriert die c++-gemeinde einfach. und im falle eines aufrüstens der sprache mit auto, würde einfach auto verlangen, daß jeder kontrollpfad den gleichen typ zurückgibt (so hoffe ich).

    aber was ist eigentlich mit

    template<typename T,int size>
    auto findElemAndIKnowItsExistent(T (&arr)[size],T const& toFind){
       for(int i=0;i<size;++i)
          if(arr[i]==toFind)
              return &arr[i];
       //hier ist was komisch. 
    }
    

    die normale lösung wäre

    template<typename T,int size>
    auto findElemAndIKnowItsExistent(T (&arr)[size],T const& toFind){
       for(int i=0;i<size;++i)
          if(arr[i]==toFind)
              return &arr[i];
       return *(T*)0;//only to make the compiler happy
    }
    

    ist aber gar nicht hübsch, wenn man kein assume hat. der happy-code wird erzeugt.

    template<typename T,int size>
    auto findElemAndIKnowItsExistent(T (&arr)[size],T const& toFind){
       for(int i=0;i<size;++i)
          if(arr[i]==toFind)
              return &arr[i];
       __assume(false);
    }
    

    so ist alles bestens und ms rult. nichmal die warnung ist noch da.

    hmm, ok, geht ja. ich nehme meine frage zurück und lehne mich zufrieden auch zurück. ich will auto haben.



  • volkard schrieb:

    ich will auto haben.

    Gibt's doch schon: Deklariert Variable auf dem Stack. 😉

    (also "auto" ist das Gegenteil von "register")

    Ich glaube nicht, daß das Schlüsselwort in der Zukunft zweckentfremdet wird! 😉

    Deine Idee ist zwar theoretisch durchführbar, aber wozu? Nur um faulen Programmierern Tipparbeit arbzunehmen? Da kennst Du C++ aber schlecht! 😉

    Für den Compiler gibt es hier und da einige Probleme: Wenn z.B. Deklarationen ohne Definitionen auftreten. Das hast Du ja explizit ausgeschlossen, aber dann können solche Funktionen niemals external linkage haben, da ja der Rückgabetyp der Funktionen zur Compile-Zeit bekannt sein muß, was aber nicht der Fall ist, wenn die Definition in der Translation Unit fehlt. D.h. beim Versuch, eine solche Funktion extern zu referenzieren, müßte laut Deiner eigenen Regel eine Fehlermeldung kommen, weil keine Definition vorhanden ist. Externe Referenzen werden ja erst beim Linkvorgang aufgelöst. Andernfalls müßte man Compiler und Linker miteinander verquicken, was aber kaum jemand machen würde. Eine andere Möglichkeit wäre ein Intermediate-Code-Linker, der aber für das Konzept dann zwingend erforderlich wäre, da vor der Code-Generierungsphase der Code der Funktionsimplementation bekannt sein muß.


Anmelden zum Antworten