Const == Code duplication?



  • Gibts zu den 2 get eine alternative?

    class Foo;
    
    class Bla
    {
    public:
    	Foo* get()
    	{
    		return f;
    	}
    
    	Foo const* get() const
    	{
    		return f;
    	}
    
    private:
    	Foo* f;
    };
    


  • Nein. In deinem Fall erst Recht nicht, weil du etwas erzwingst, das nicht einmal von const gefordert wurde.

    //edit ich hole etwas weiter aus:

    Das ist bereits perfekt const-correct:

    class Bla
    {
    public:
        Foo* get()const
        {
            return f;
        }
    private:
        Foo* f;
    };
    

    Warum? Du übergibst den Zeiger f als Kopie, damit ist f unveränderbar. const-correctness erstreckt sich aber nur über den Bereich eines Objektes - alles was hinter einem Zeiger liegt ist nach dieser Definition außerhalb. Deswegen wrde der Compiler bei so einer Deklaration nie meckern.

    Anders sieht es hier aus

    class Bla
    {
    public:
        Foo*& get()
        {
            return f;
        }
    
        Foo*const& get() const
        {
            return f;
        }
    
    private:
        Foo* f;
    };
    

    Hier erlaubst du in der non-const Version, dass f selbst verändert wird. Das ist in der const-Version nach const-Definition nicht erlaubt, also brauchst du eine Zweite Methode. Das Objekt hinter dem Zeiger ist aber immer noch veränderbar.
    Man hätte sich natürlich überlegen können, ob man da einen Automatismus hätte einbauen können - haben die Leute vom Standard aber nicht gemacht.

    Das was du machst ist also: "f ist immer unveränderbar, aber wenn Bla const ist, ist auch *f unveränderlich". Und das es dafür einen sinnvollen Automatismus geben könnte ist auszuschließen.



  • otze schrieb:

    class Bla
    {
    public:
        Foo* get()const
        {
            return f;
        }
    private:
        Foo* f;
    };
    

    Das ist bereits perfekt const-correct:

    Das kommt darauf an wie man const correctness für sich definiert. Ich betrachte Konstanz als logische Konstanz, und wenn durch das Verändern der Foo Instanz bei f das Bla Objekt logisch verändert wird (was der Autor von Bla entscheiden muss) ist das Beispiel hier nicht korrekt. Das kann genauso auch andersherum gehen: Es werden Daten eines Objekts verändert, aber logisch ändert sich das Objekt nicht. Diese Daten kann man dann mutable deklarieren, so dass man sie in const Methoden verändern kann.

    Das Beispiel des Threaderstellers kann also durchaus Sinn machen, wenn eine konstante Bla Referenz keinen nicht konstanten Zeiger auf die Foo Instanz rausrücken darf. Dass der Compiler da keine Problem mit hat, ist eine ganz andere Geschichte.

    ps: Beim zweiten Lesen ist mir gar nicht mehr so klar, was jetzt Deine Aussage war.. naja ich poste trotzdem mal:-)



  • Diese Code-Duplikation kann durchaus vorkommen. Aber das kannst du doch einfach umbiegen:

    struct some_class {
       const int& get_acess() const {
          log_access();
          // andere schöne Sachen
          return member_;
       }
    
       int& get_element() {
          return const_cast<int&>(static_cast<const some_class*>(this)->get_access());
       }
    };
    

    Macht aber nur Sinn, wenn in diesem getter viel passiert.



  • Ad aCTa schrieb:

    Diese Code-Duplikation kann durchaus vorkommen. Aber das kannst du doch einfach umbiegen:

    struct some_class {
       const int& get_acess() const {
          log_access();
          // andere schöne Sachen
          return member_;
       }
    
       int& get_element() {
          return const_cast<int&>(static_cast<const some_class*>(this)->get_access());
       }
    };
    

    Macht aber nur Sinn, wenn in diesem getter viel passiert.

    Das ist so hässlich, dass es weh tut.



  • mmmmmmmm schrieb:

    Das ist so hässlich, dass es weh tut.

    Weil man es normalerweise andersherum macht:

    struct Test {
        int val;
        int& get() {
            return val;
        }
        int const& get() const {
            return const_cast<Test*>(this)->get();
        }
    };
    


  • l'abra d'or schrieb:

    mmmmmmmm schrieb:

    Das ist so hässlich, dass es weh tut.

    Weil man es normalerweise andersherum macht:

    struct Test {
        int val;
        int& get() {
            return val;
        }
        int const& get() const {
            return const_cast<Test*>(this)->get();
        }
    };
    

    Müsstest du das Ergebnis nicht noch nach const int& casten?



  • wxSkip schrieb:

    Müsstest du das Ergebnis nicht noch nach const int& casten?

    Nein, warum? Geschieht doch schon implizit. Bei einem "normalen" getter castest du doch auch nicht noch explizit auf const ref. :p



  • l'abra d'or schrieb:

    wxSkip schrieb:

    Müsstest du das Ergebnis nicht noch nach const int& casten?

    Nein, warum? Geschieht doch schon implizit. Bei einem "normalen" getter castest du doch auch nicht noch explizit auf const ref. :p

    Ich benutze sowieso kein const 😉 (jedenfalls selten)


Anmelden zum Antworten