2017-12-16 9 views
2

Kann const_cast verwendet werden, um nicht konstante Versionen bereits implementierter Methoden zu erstellen? Ich denke, ich habe etwas in dieser Richtung gesehen (mit Empfehlung für die Const-Methode, um die eigentliche Arbeit zu machen), aber ich bin nicht wirklich sicher, wie es funktionieren soll.Verwenden von const_cast zum Erstellen einer nichtkonstanten Variante von Methoden

Value& const search(key) const { 
    // find value with key 
    return value; 
} 

Value& search(key) { 
    return const_cast<Value&>(search(key)); 
} 

Wenn nicht auf diese Weise, was ist die empfohlene Methode zum Erstellen von nicht-const-Funktionen ohne Code-Duplizität?

+1

Zuerst das Wort "Duplizität" nachschlagen. Es bedeutet nicht "Duplizierung". Ich warte .... Okay. Const wegwerfen ist etwas, das du normalerweise nur dann tust, wenn du dich in einer schlimmen Lage und gegen eine Deadline befindest. Es gibt Ausnahmen. Zum Beispiel, wenn eine Klasse einen Cache hat, der für die Öffentlichkeit transparent ist. Als const in die Sprache eingeführt wurde, gab es eine Debatte darüber, ob "const" wirklich, wirklich konstant oder "als ob" konstant bedeuten sollte. "Als ob" gewonnen und damit const geboren wurde. –

+0

Zugehörig: https://Stackoverflow.com/q/123758/1896169 – Justin

Antwort

3

Der einfachste Weg, es zu tun ist, mit as_const von C++ 17:

Value& search(key) { 
    return const_cast<Value&>(std::as_const(*this).search(key)); 
} 

Ohne sie Sie diese stattdessen tun können (oder es selbst zu implementieren, ist es nicht sehr schwer ist)

Value& search(key) { 
    return const_cast<Value&>(static_cast<const T&>(*this).search(key)); 
} 

Wo T ist der Typ Ihrer Klasse (Sie können eine generische Lösung mit decltype haben, aber es wird wirklich hässlich, weil decltype(*this) ein Referenztyp ist).

Sie können die as_const Implementierung here oder die generische Besetzung here betrachten.

+0

Gibt es andere Möglichkeiten, es zu tun, kompatibel mit C++ 14? – Davar

+0

@Davar aktualisiert. – user975989

+0

Sie können "this" auf den entsprechenden 'const'-Zeiger übertragen oder eine eigene Version von' as_const() 'definieren, z. B.' template T const & as_const (T const & x) {return x; } '. Persönlich mag ich es nicht, "const" wegzuwerfen, und ich würde lieber einen Templaizealgorithmus implementieren, der möglicherweise 'static' oder' friend'-Funktionen verwendet und sein Ergebnis in der 'const'/non-const'Überlastung zurückgibt. –

1

Zwei Ansätze.

Erstens:

namespace notstd{ // backported C++17 
    template<class T> 
    T const& as_const(T& t){return t;} 
    template<class T> 
    T const&& as_const(T&& t){return t;}  
} 
namespace utility { // not ever in std 
    template<class T> 
    T& remove_const(T const& t){return const_cast<T&>(t);} 
    template<class T> 
    T&& remove_const(T const&& t){return const_cast<T&&>(t);} 
} 

dann:

Value& const search(Key key) const { 
    // find value with key 
    return value; 
} 

Value& search(Key key) { 
    return utility::remove_const(notstd::as_const(*this).search(key)); 
} 

oder alternativ:

Value& const search(Key key) const { 
    return search(*this, key); 
} 

Value& search(Key key) { 
    return search(*this, key); 
} 
private: 
    template<class Self> 
    friend decltype(auto) search(Self& self, Key key){ 
    // find value with key 
    } 

wo wir die Arbeit an einen Freund Vorlage delegieren, wo self ist vielleicht-konst.

Verwandte Themen