non-const-Getter aus const-Version ableiten?



  • So viel Code ist es jetzt auch nicht, es handelt sich um eine Suchfunktion. Aus einer Liste soll ein bestimmtes Element genommen werden und das wird zurückgegeben.

    Würde ich die Suche jetzt in eine eigene Funktion auslagern, hätte ich doch dasselbe Problem wieder? Meine Suche ist nicht Mal binär, sondern iterativ. Und der Schleifeniterator ist eben auch const oder nicht-const.



  • So viel Code ist es jetzt auch nicht, es handelt sich um eine Suchfunktion.
    

    Kennst du std::find?

    Die Antwort in deinem Fall ist also: Schreib dir deinen eigenen Iterator + Const-Iterator. Die dort auftretende Codeduplikation kannst du mit Templates lösen.



  • Wenn std::find nicht genuegt gibts ja noch std::find_if, dann kannste die Bedingungen an dem Element in eine extra funktion (oder auch lambda, wenn es nicht zu viel Code ist) pruefen.



  • Eric Cartman schrieb:

    Ich hab irgendwo mal gelesen, dass man das sogar so machen soll

    Joa, ich glaube die Empfehlung kommt von Scott Meyers - Effective C++. Obwohl er es so macht:

    return const_cast<B&>( static_cast<const A&>( *this ).get() );
    


  • Ja, Scott Meyers empfiehlt das in seinem Effective C++.

    Normalerweise denkt man ja eher umgekehrt, also so:

    class Foo
    {
    	Bar x;
    public:
    	Bar& getX()
    	{
    		return this->x;
    	}
    
    	const Bar& getX() const
    	{
    		return this->getX();
    	}
    };
    

    Aber das ist nicht wirklich const-correct, da die const Version nicht dann aufgerufen wird, wenn man es erwartet (und umgekehrt). Wer die Begründung genau wissen will, dem zitiere ich das hier vom Meyers.

    Die Methode oben würde ich schon empfehlen, in eine Funktion abkapseln kann man ja immer noch. Ich weiss auch nicht was daran hässlich oder unschön sein soll? Ist halt besser als redundanter Code...



  • find_if kenne ich, das wäre aber auch nicht kürzer. Ich würde dennoch redundanten Code erzeugen, den ich ungern zwei Mal schreiben würde, egal wie kurz er ist (kann ja auf Dauer noch länger werden, dann muss ich trotzdem zwei Mal anpassen).

    Skym0sh0:
    Das wäre doch einfach Endlosrekursion, oder? In der const-Variante ist der this-Zeiger doch immer noch const, also wird auch wieder die const-Variante aufgerufen.

    Wenn der Scott Meyers das empfiehlt, kann die Methode ja nicht so falsch sein. Wunderbar, vielen Dank! 🙂



  • Eisflamme schrieb:

    find_if kenne ich, das wäre aber auch nicht kürzer. Ich würde dennoch redundanten Code erzeugen, den ich ungern zwei Mal schreiben würde, egal wie kurz er ist (kann ja auf Dauer noch länger werden, dann muss ich trotzdem zwei Mal anpassen).

    Ein getter ist eine Zeile lang. Nicht mehr und nicht weniger.



  • Ich habe schon beschrieben, dass meine Suche ein Finden in einem Container impliziert. Ich habe auch nicht gesagt, nach welchen Kriterien ich durchsuche und ob das Finden des Elements auf einem trivialen Attributvergleich basiert.

    Und ob man unter:

    Containter::iterator it = std::find_if(container.begin(), container.end(), [whatEver](Object& obj)
    {
        return obj.whatEver == whatEver;
    });
    return it == container.end() ? nullptr : &*it;
    

    jetzt einen Einzeiler verstehen muss, würde ich auch anzweifeln.

    Gerne kann mir jemand aber auch den Vorteil zu:

    BOOST_FOREACH(Object& obj, container)
    {
        if(obj.whatEver == whatEver)
            return &obj;
    }
    return nullptr;
    

    erklären, letzteres erscheint mir nämlich kürzer und lesbarer.



  • Eisflamme schrieb:

    geht Folgendes bzw. würdet ihr es empfehlen?

    Wenn das so Sinn macht mit der Überladung, 2mal ja.



  • Eisflamme schrieb:

    Und ob man unter [...] jetzt einen Einzeiler verstehen muss, würde ich auch anzweifeln.

    Deine Funktion ist auch kein typischer Getter, sondern ein Sucher. "get" heisst "gib mir" -- entsprechend ist die Erwartung, dass man das Gewünschte auch bekommt. Bei dir hingegen kann der zurückgegebene Wert ungültig sein.



  • Nagut, ich kenne da solche Spezialbegriffe nicht. Dass der Getter nicht trivial ist, sollte ja von Anfang an klar gewesen sein. Und in die weite Definition von einem Getter hätte ich das Ding ja durchaus eingeordnet oder nicht? Sucher habe ich noch nie gehört.



  • "Sucher" ist kein offizieller Begriff, den hab ich gerade erfunden 😉

    Ja, im weiten Sinne könnte man vieles als Getter sehen, z.B. auch operator[] ... Die Frage ist, wo du die Grenze ziehst. Nicht alles, was etwas zurückgibt, ist ein Getter, sonst wird der Begriff bedeutungslos. Ich versuchte mit meinem Post nur zu erklären, was Shade Of Mine wahrscheinlich meinte.


Anmelden zum Antworten