Overloading the C++ indexing subscript operator [] in a manner that allows for responses to updates

后端 未结 6 1229
我在风中等你
我在风中等你 2020-12-08 10:32

Consider the task of writing an indexable class which automatically synchronizes its state with some external data-store (e.g. a file). In order to do this the class would n

6条回答
  •  慢半拍i
    慢半拍i (楼主)
    2020-12-08 11:10

    Another elegant (IMHO) solution... Actually it is based on the fact that the const overload is called only when used on const object. Lets first create two [] overloads - as it is required, but using different locations:

    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];
    }
    

    Now you should create a shadow reference of your object when you need to "read" it as follows:

    const Indexable& myIndexableRead = myIndexable; // create the shadow
    Type a = myIndexableRead[2]; //Access
    myIndexable[3] = a;  //Modification
    

    Creating this shadow declaration does not actually create anything in the memory. It just creates another name for your object with "const" access. It is all resolved at the compilation stage (including usage of const overload) and does not affect anything in runtime - neither memory nor performance.

    And the bottom line - it is much more elegant (IMHO) than creating any assignment proxies, etc. I must state that the statement "From the operator[] you can only really tell access" is incorrect. According to the C++ Standard, returning dynamically allocatted object or global variable by reference is ultimate way to allow its direct modification, including [] overload case.

    Following code has been tested:

    #include 
    
    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;
    }
    

    And the results are:

    20 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 50

提交回复
热议问题