Was macht man mit solch einer Fehlermeldung?



  • Eine Menge Antworten inzwischen, hatte etwas Scheu, hier wieder reinzuschauen. Es gab ja viele Anregungen, und so wie ich manches verstehe, gibt es viele Spekulationen.
    Mein Rectzb ist dargestellt ein Polygon. Deshalb brauche ich auch vier Punkte, weil die Ecken nicht immer rechte und selbe Winkel sind. Das muss ich aber noch schauen, denn anfangs hatte ich ja auch nur zwei Point2D.

    Vielleicht wäre es hilfreich, wenn man noch meine Klasse Plot2D, wo das alles dargestellt wird, zeige, habe aber Angst, das dies einen Rattenschwanz an Vorschlägen bringt, wo man den Überblick verliert. Wenn schon das kleine Rectso ergiebig ist. Vielleicht in einem neuen Thread.

    Wenn es noch Anmerkungen gibt, die ich jetzt nicht berücksichtigt habe, gerne wiederholen. Wollte mich nur erstmal relativ zügig wieder melden.



  • Meine generelle Anmerkung ist, dass weniger manchmal mehr ist, insbesondere wenn der Anwendungsbereich schon von vorn beschränkt ist. Ist es zum Beispiel nötig, dass alles getemplatet ist? Templates verlängern die Compilezeit und machen den Code komplizierter. Würdest du irgendwas verlieren, wenn du die Klasse mit int-Koordinaten machst? Offenbar ist die ja zum Beispiel gar nicht für float-Zahlen oder gar komplexe Koordinaten geeignet.

    Andererseits ist es natürlich schön, eine generelle und wiederverwertbare Klasse zu haben.

    Ich finde aber, dass man die Diskussion insbesondere bei so etwas einachem wie 2 Punkten übertreiben kann.

    Am probelmatischten finde ich, dass nicht sofort an den Namen ersichtlich ist, das das alles soll. Bei deinem Dim gebe ich 2 Punkte in den Konstruktor (warum muss ich da 4 Einzelwerte statt 2 Punkte reintun, wo du doch Punkt2D hast?) und kann dann x() abfragen - hä? Verstehe schon die Berechnung nicht. Funktionsnamen wie toPoint und toLength schreien vom Namen her danach, Point und Length zu returnen, sind aber bei dir void. Brauchst du wirklich die 6 Member-Variablen? Das erscheint mir zu kompliziert.



  • Das Dim-Beispiel sollte nur zeigen, wie ich mich mit width- unhd height-Angaben schwer getan habe. Ist nicht mehr aktuell. Und lösche ich auch, weil es keinen Grund mehr gibt, darüber zu sprechen. Hatte aber bis dahin seine Arbeit getan.

    Bezüglich den templates habe ich auch in diese Richtung überlegt, ob zum Schluß, wenn eh nur noch mit bestimmten Typen gerechnet wird, nur diese zu verwenden. Aber ist ja keine große Änderung. Dann schreibe ich bei der betreffenden Klasse eben um, using val_t = float oder ähnlich.



  • Sorry, ich wollte nicht wieder undankbar wirken. Bzüglich der Dim-Klasse hätte ich nur "ja" antworten können, weil eben Geschichte.



  • @It0101 sagte in Was macht man mit solch einer Fehlermeldung?:

    @zeropage sagte in Was macht man mit solch einer Fehlermeldung?:

    	val_t right() const { return points_[2].x(); }
    	val_t top() const { return points_[2].y(); }
    

    Sowas ist halt extrem ungut, wenn du nicht sicherstellst, dass "points_" wirklich mindestens 3 Elemente hat. Wie z.B. im Falle deines Default-Konstruktors. In dem Fall wäre dein Vector nämlich leer.
    Deswegen macht man solche "getter" eigentlich nicht.

    Im Fehlerfall bekommst du hier einen Segmentation-Fault und hast keine Ahnung wo dir das Ding gerade um die Ohren geflogen ist. Oder du bekommst irgendwelche Werte zurück, und hast plötzlich ein merkwürdig geformtes Rechteck.

    Ich schließe mich hier den Sportfreunden an, die sagen: Lieber das Rechteck durch zwei Punkte definieren ( oben-links, unten-rechts ). Vectoren oder Arrays sind hier nicht nötig.

    Gut, dann bleibt es dabei:

    • gelöscht


  • so, hoffentlich finito.

    template<typename T>
    class Rect
    {
    	using val_t = T;
    public:
    	Rect(const val_t x0, const val_t y0, const val_t x, const val_t y) 
    		: p0{ x0, y0 }, p{ x, y } {}
    
    	val_t left() const { return p0.x; }
    	val_t bottom() const { return p0.y; }
    	val_t right() const { return p.x; }
    	val_t top() const { return p.y; }
    
    private:
    	struct point
    	{
    		val_t x = 0;
    		val_t y = 0;
    	} p0, p;
    };
    


  • @zeropage Naja man könnte die Punkte noch topLeft und rightBottom nennen, und die ctor Parameter entsprechend left, top, right, bottom. Dann wäre das einfacher zu lesen & verwenden.

    Und: Wenn du schon einen typedef ala val_t verwendest, und den in der Definition verwendest, würde ich den tendenziell eher public machen.



  • @hustbaer sagte in Was macht man mit solch einer Fehlermeldung?:

    Und: Wenn du schon einen typedef ala val_t verwendest, und den in der Definition verwendest, würde ich den tendenziell eher public machen.

    Vielleicht ne blöde Frage, aber warum eigentlich? Der Klasse selbst ist es ja wurscht?



  • @zeropage sagte in Was macht man mit solch einer Fehlermeldung?:

    @hustbaer sagte in Was macht man mit solch einer Fehlermeldung?:

    Und: Wenn du schon einen typedef ala val_t verwendest, und den in der Definition verwendest, würde ich den tendenziell eher public machen.

    Vielleicht ne blöde Frage, aber warum eigentlich? Der Klasse selbst ist es ja wurscht?

    wozu eigentlich "val_t" überhaupt?



  • @It0101 sagte in Was macht man mit solch einer Fehlermeldung?:

    wozu eigentlich "val_t" überhaupt?

    Gewohnheit.



  • @zeropage sagte in Was macht man mit solch einer Fehlermeldung?:

    @It0101 sagte in Was macht man mit solch einer Fehlermeldung?:

    wozu eigentlich "val_t" überhaupt?

    Gewohnheit.

    Was ist denn der Vorteil ? warum nicht einfach direkt "T" nehmen?



  • Weil es egal ist.



  • @zeropage sagte in Was macht man mit solch einer Fehlermeldung?:

    Weil es egal ist.

    Nein. Ist es nicht. Bei "T" weiß sofort jeder Leser des Quellcodes was gemeint ist.

    Ist kein großes Drama, da hast du recht. Aber zumindest ungewöhnlich.

    Wobei das hier genauso möglich ist. Der Typ muss nicht zwangsläufig "T" heißen.

    template
    <typename val_t>
    class myClass
    {
    };
    


  • @zeropage sagte in Was macht man mit solch einer Fehlermeldung?:

    @hustbaer sagte in Was macht man mit solch einer Fehlermeldung?:

    Und: Wenn du schon einen typedef ala val_t verwendest, und den in der Definition verwendest, würde ich den tendenziell eher public machen.

    Vielleicht ne blöde Frage, aber warum eigentlich? Der Klasse selbst ist es ja wurscht?

    Naja schlimm ist es nicht. Ich finde es nur komisch (ohne guten Grund) einen Typ-Namen in der Signatur von public Funktionen zu verwenden, den man von ausserhalb nicht verwenden kann.

    Ich persönlich würde da genau so wie @It0101 es schon vorgeschlagen hat gar keinen Typedef/Alias verwenden, sondern einfach T hinschreiben. Weil das IMO einfacher zu lesen ist - man weiss dann sofort was T ist und muss nicht erst nochmal nachsehen was val_t ist.

    Wenn du es dagegen machst um z.B. in weiteren Tempaltes die mit U=Rect<T> instanziert werden einfachen Zugriff auf T zu erhalten (über typename U::val_t), dann müsste val_t auch public sein.



  • Und ich dachte, val_twäre intuitiver zu lesen 😕



  • Naja in diesem einfachen Fall wird es Wurst sein. Und du darfst das natürlich machen wie du willst. Ich sage nur ich persönlich finde es komisch im public Interface private Typedefs/Aliase zu verwenden.



  • @hustbaer sagte in Was macht man mit solch einer Fehlermeldung?:

    Ich sage nur ich persönlich finde es komisch im public Interface private Typedefs/Aliase zu verwenden.

    Das ist ja auch wieder was anderes. Ich wusste nicht, das das komisch ausschaut. Habe das bisher auch nur im public-Bereich gesehen. Weil aber außer der Klasse das sonst niemand benutzen kann, dachte ich, kann ich das auch private machen. Ist halt ein Stück Unerfahrenheit.



  • Und was ist z.B. mit folgendem Code?

    Rect<int> r(0, 0, 1, 1);
    	
    decltype(r)::val_t x = r.left();
    

    -> "error: ‘using val_t = int’ is private within this context", s.a. Ideone-Code.

    Oder was @hustbaer meint, z.B.

    template<T, U = Rect<T>> do_something(const U &u)
    {
        typename U::val_t x = u.left();
        // oder genauso
       decltype(u)::val_t x2 = u.left();
    }
    

    (dabei muß Rect<T> noch nichteinmal die Standard-Templateklasse sein, dies habe ich nur zur besseren Veranschaulichung hingeschrieben).

    Also private: using (bzw. typedef ) nur für ebenfalls private Member benutzen, oder aber ebenso public setzen.



  • Ok, Alles klar. Danke für die Hinweise.



  • @Th69 sagte in Was macht man mit solch einer Fehlermeldung?:

    Oder was @hustbaer meint, z.B.

    template<T, U = Rect<T>> do_something(const U &u)
    {
        typename U::val_t x = u.left();
        // oder genauso
       decltype(u)::val_t x2 = u.left();
    }
    

    In dem Fall ginge es ja, weil man eh direkt T hat. Ich meinte eher

    template<class U> void do_something(const U &u)
    {
        // U::T geht nicht :(
        // auto ginge, aber könnte u.U. ein anderer Typ sein (standard promotions etc.)
        // und es könnte ja sein dass wir aus irgend einem grund genau den selben typ brauchen/haben wollen
        typename U::val_t foo = (u.right() - u.left()) * 2 + (u.bottom() - u.top()) * 2; // geht :)
    }
    

Anmelden zum Antworten