Piszę klasę CustomVector wewnętrznie przechowywania danych za pomocą standardowego Vector:C++ Pisanie const wektory z wskazówki dla non const
template <class T>
class CustomVector {
friend class CustomVector_ref<T>;
public:
...
private:
std::vector<T> _data;
};
Następnie, w celu wydobycia podwektorach z CustomVector używam klasę przechowującą wskaźniki do każdego elementu danych:
template <class T>
class CustomVector_ref {
public:
//Returns the value stored in CustomVector
//and pointed-to by _data_ref
T& operator[] (size_t id) { return *_data_ref[id] }
const T& operator[] const (size_t id) { return *_data_ref[id] }
...
private:
std::vector<T*> _data_ref;
};
teraz, aby zilustrować mój problem, wystarczy rozważyć prosty costructor budynek odniesienie do wszystkich elementów CustomVector
template<class T>
CustomVector_ref<T>::CustomVector_ref(CustomVector<T>& cv)
{
for (T& el : cv._data)
_data_ref.push_back(&el);
}
To działa dobrze, ale jeśli mam const CustomVector, muszę również zdefiniować konstruktor:
template<class T>
CustomVector_ref<T>::CustomVector_ref(const CustomVector<T>& cv)
{
for (const T& el : cv._data)
_data_ref.push_back(const_cast<T*>(&el));
}
który działa zbyt, ale jeśli obiekt CustomVector_ref nie jest zadeklarowane jako const, a następnie non -const operator [] możliwe jest zapisywanie danych w stałym obiekcie CustomVector.
const CustomVector<int> cv(...) //CostumVector is somehow constructed,
//that does not matter now
std::cout<<cv[0]<<std::endl; //output 1 for example
CustomVector_ref<int> cvr(cv)
cvr[0] = 2;
std::cout<<cv[0]<<std::endl; //now cv[0] stores 2
Można tego uniknąć?
Zauważyłem, że to dzieje się również ze standardowymi wektorami, np
const std::vector<int> v(1,1);
std::vector<int*> vp;
vp.push_back(const_cast<int*>(&v[0]));
*vp[0] = 2;
std::cout<<v[0]<<std::endl; // now v[0] stores 2, not 1
Tak, ponieważ jest to standard C++, nie przejmuj się zbytnio, aby naprawić mój CustomVector, ale byłoby miło wiedzieć jeśli istnieje (niezbyt skomplikowane) rozwiązanie.
Należy się zastanowić nad prostym faktem, że standardowe pojemniki biblioteczne definiują dwie różne klasy iteratora: 'iterator' i' const_iterator'. Jest ku temu dobry powód i właśnie odkryłeś, jaki jest ten powód. Twoja sytuacja jest zupełnie analogiczna. Musisz zaimplementować dwie różne referencje, zmienną i referencję 'const'. Aby uzyskać dodatkowe punkty, zmienne referencje powinny być rzutowane na referencje 'const', więc można je przekazać do funkcji, które pobierają odwołania' const' jako argumenty. –
Wahając się oznaczyć to jako dupe, ale jest to bardzo realne https://stackoverflow.com/questions/44882363/does-const-iterator-really-need-to-be-a-different-than-iterator – user463035818
Co o użyciu 'CustomVector_ref'?Żadna const_cast nie jest potrzebna w ten sposób. –
geza