Hallo,
ich kann mir bei const/non-const Funktionspärchen nie merken, welcher cast gültig ist. Ich möchte zwei von der Funktionalität identische Funktionen durch eine Funktion implementieren, eine const- und eine non-const-Variante. Da gibt's jetzt zwei Möglichkeiten:
Implementierung in der const-Funktion
In der non-const Funktion wird nach const gecastet, die const-Funktion aufgerufen und das Ergebnis nach non-const gecastet.
Implementierung in der non-const-Funktion
In der const Funktion wird nach non-const gecastet, die non-const-Funktion aufgerufen und das Ergebnis nach const gecastet.
Nach meinem Verständnis sollte Variante 1 die richtige sein, ich darf ein non-const Objekt nach const casten. Weil ich an dieser Stelle weiß, dass das Objekt non-const ist, darf ich es auch wieder von const nach non-const zurückcasten.
Variante 2 sollte falsch sein, da die non-const Funktion das Objekt verändern könnte, und das darf bei einem const Objekt nicht passieren. Also ist der cast von const nach non-const nicht erlaubt. Oder darf ich das hier brechen, weil ich weiß, dass auch die non-const Variante das Objekt nicht verändert?
Im konkreten Beispiel funktioniert das für iteratoren nicht, ein iterator kann zwar in einen const_iterator konvertiert werden, aber nicht umgekehrt. Für die Zeigervariante funktioniert das.
Was ist also die korrekte Lösung für iteratoren?
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
struct Test
{
std::vector<int> v;
using iterator = std::vector<int>::iterator;
using const_iterator = std::vector<int>::const_iterator;
iterator find( int val )
{
return std::find( v.begin(), v.end(), val );
}
const_iterator find( int val ) const
{
return const_cast<Test*>( this )->find( val );
}
int* find2( int val )
{
return const_cast<int*>( const_cast<Test const*>( this )->find2( val ));
}
int const* find2( int val ) const
{
auto pos = std::find( v.begin(), v.end(), val );
return pos == v.end() ? nullptr : &(*pos);
}
};
int main()
{
Test c;
Test const n;
c.find( 13 );
n.find( 13 );
c.find2( 13 );
n.find2( 13 );
return 0;
}```