You need to solve this problem with a proxy type containing a reference to an Array object and the index passed to your operator[] . This type of proxy will be implicitly converted to float and can be assigned from float , making access (mostly 1 ) transparent.
We also break rule three in this case and implement the copy-assignment operator to assign the value of one element of the array to another so that foo[0] = foo[1] works properly.
We need to make the following changes:
- Rename the existing
operator[] and make it private; it will only be used by the proxy type. - Create a new
operator[] that returns a proxy type value. - Enter the type of proxy.
Change 1, inside the definition of Array :
friend class ArrayElement; // So that ArrayElement can use access() private: float& access(int index) { if(index>=_size) { float* NewArray=new float[index+1]; for(int i=0;i<_size;++i) NewArray[i]=_array[i]; for(int i=_size;i<index+1;++i) NewArray[i]=0; delete[] _array; _array=NewArray; _size=index+1; } return _array[index]; }
Edit 2:
// Inside of Array public: ArrayElement operator[](int index); // Implementation outside of Array ArrayElement Array::operator[](int index) { return ArrayElement(*this, index); }
Edit 3:
class ArrayElement { friend class Array; // So that Array can use our private constructor private: ArrayElement(Array & array, int index) : array(array), index(index) { } public: // Allows "foo[1] = 2" ArrayElement const & operator=(float v) const { array.access(index) = v; return *this; } // Violation of the rule of three, but it makes sense in this case. // Allows "foo[1] = foo[2]" ArrayElement const & operator=(ArrayElement const & other) const { array.access(index) = other; return *this; } // Allows "float x = foo[1]" operator float() const { return array.access(index); } private: Array & array; int index; };
(Minor final change, you need to forward the declaration of ArrayElement before defining Array .)
See this working example .
1 . One caveat to this approach is the use of output type ( auto in C ++ 11) when accessing an array:
auto x = an_array[1];
Now x is an ArrayElement instead of a float , and its value will change when an_array[1] changes. Trying to set a different value float x will also change the value in an_array[1] , since x is just a proxy for this value.
Compare this to the general behavior of std::vector , where auto x = a_vector[0] will result in x being the type of the vector element, and therefore will contain an independent copy of the value stored in the vector.
Note, however, that the specialization std::vector<bool> exactly matches the approach given here (returns a proxy object), and therefore it has the same auto Caution ! You can take this as a blessing on this approach.