2016-05-09 20 views
10

Gibt es eine gute Möglichkeit, um die const_cast unten zu vermeiden, während const Richtigkeit zu halten?Vermeiden von const_cast beim Aufruf von std :: set <Type*> :: finden

Ohne const_cast wird der folgende Code nicht kompiliert. set::find erhält einen konstanten Verweis auf den Schlüsseltyp des Satzes, in unserem Fall garantiert es also, den übergebenen Zeigerwert nicht zu ändern; Es ist jedoch nichts garantiert, nicht zu ändern, worauf der Zeiger zeigt.

class C { 
public: 
    std::set<int*> m_set; 

    bool isPtrInSet(const int* ptr) const 
    { 
     return m_set.find(const_cast<int*>(ptr)) != m_set.end(); 
    } 
}; 
+0

Sie geben einen Iterator in einer Funktion zurück, die einen 'bool' zurückgibt, dieser Code wird zur Zeit nicht kompiliert. Möchten Sie 'return m_set.find (const_cast (ptr)) 'verwenden? = Std :: cend (m_set);'? – user2296177

+0

Whoops, behoben. Danke – Danra

+0

'std :: find' könnte helfen. Ich frage mich, ob sie es jemals teilweise spezialisieren, um in logarithmischer Zeit auf 'std :: set'-Grenzen zu laufen. – bipll

Antwort

0

Wenn Sie const int* s speichern möchten, speichern Sie dann const int* s. Wenn Sie stattdessen int* s speichern wollen, dann tun Sie das, aber Sie können nicht so mischen und passen (zumindest nicht ohne den Hack, den Sie bereits benutzt haben).

Wählen Sie einen aus und bleiben Sie dabei.

+6

Ich brauche 'set ' da die Ints müssen durch * einige * Methoden geändert werden. Einige andere Methoden sind jedoch garantiert nicht die Ints zu ändern, und es wäre schön, diese Versprechen in der Schnittstelle dieser Methoden zu vermitteln, in diesem Beispiel wird dies durch die Deklaration des Parameters const int * getan. – Danra

+3

@Danra: Dann sieht dein 'const_cast' gut aus. –

+0

@Danra Ich verstehe deine Logik nicht. Wenn die Methode mit const gekennzeichnet ist, kann 'm_set' nicht geändert werden. Wechseln Sie die Position von "const": 'int * const ptr' und der Compiler-Fehler verschwindet. –

0

Gibt es einen guten Weg, um den unten stehenden const_cast zu umgehen, während die const Korrektheit beibehalten wird?

Ich bin mir nicht sicher, ob das, was ich vorschlagen werde, als "guter Weg" gilt. Sie können jedoch die const_cast vermeiden, wenn es Ihnen nichts ausmacht, selbst über den Inhalt des Sets zu iterieren. Denken Sie daran, dass damit eine O (log (N)) - Operation in eine O (N) -Operation umgewandelt wird.

bool isPtrInSet(const int* ptr) const 
{ 
    for (auto p : m_set) 
    { 
     if (p == ptr) 
     { 
     return true; 
     } 
    } 
    return false; 
} 
+1

Gibt es jemanden in guter Meinung, der O (N) gegen O (log (N)) bezahlen würde, nur um const_cast zu vermeiden? – Slava

+1

@Slava, ich würde nicht, aber ich kann nicht für alle sprechen. –

2

Ich möchte die zugrunde liegende Logik erklären, warum dies unmöglich ist.

Angenommen, set<int*>::find(const int*) wäre legitim. Dann könntest du folgendes machen:

set<int*> s; 
const int* p_const; 
// fill s and p 
auto it = s.find(p_const); 
int* p = *it; 

Hey presto! Sie haben const int* in int* umgewandelt, ohne const_cast durchzuführen.

+1

Nach Ihrer Logik sollte der Vergleich von const und nicht const Zeiger illegal sein, oder jemand kann diesen Hokuspokus mit 'find_if()' machen. Ziemlich verworrene Logik imho – Slava