Еще одно элегантное (ИМХО) решение ...
На самом деле это основано на том факте, что перегрузка const вызывается только при использовании объекта const.
Сначала давайте создадим две перегрузки [] - как требуется, но в разных местах:
Type& operator[](int index)
{
assert(index >=0 && index < size);
return stateWrite[index];
}
const Type& operator[](int index) const
{
assert(index >=0 && index < size);
return stateRead[index];
}
Теперь вам нужно создать теневую ссылку на ваш объект, когда вам нужно «прочитать» его следующим образом:
const Indexable& myIndexableRead = myIndexable; // create the shadow
Type a = myIndexableRead[2]; //Access
myIndexable[3] = a; //Modification
Создание этого теневого объявления фактически не создает ничего в памяти. Он просто создает другое имя для вашего объекта с доступом «const». Все это решается на этапе компиляции (включая использование перегрузки const) и не влияет ни на что во время выполнения - ни на память, ни на производительность.
И нижняя строка - это намного более элегантно (ИМХО), чем создание каких-либо прокси присваиваний и т. Д. Я должен заявить, что оператор " От оператора [] вы можете действительно только сказать доступ "неверно. В соответствии со стандартом C ++, возвращение динамически размещенного объекта или глобальной переменной по ссылке является наилучшим способом разрешить его прямое изменение, включая [] случай перегрузки.
Следующий код был протестирован:
#include <iostream>
using namespace std;
class SafeIntArray {
int* numbers;
int size;
static const int externalValue = 50;
public:
SafeIntArray( unsigned int size = 20 ) {
this->size = size;
numbers = new int[size];
}
~SafeIntArray() {
delete[] numbers;
}
const int& operator[]( const unsigned int i ) const {
if ( i < size )
return numbers[i];
else
return externalValue;
}
int& operator[]( const unsigned int i ) {
if ( i < size )
return numbers[i];
else
return *numbers;
}
unsigned int getSize() { return size; }
};
int main() {
SafeIntArray arr;
const SafeIntArray& arr_0 = arr;
int size = arr.getSize();
for ( int i = 0; i <= size ; i++ )
arr[i] = i;
for ( int i = 0; i <= size ; i++ ) {
cout << arr_0[i] << ' ';
}
cout << endl;
return 0;
}
И результаты:
20 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 50