I'd probably solve this with a proxy object:
class Xproxy { int& changeable; int& unchangeable; Xproxy(int& c, int& u) : changeable(c), unchangeable(u) {} Xproxy& operator=(int i) { changeable=i return *this } operator int() { return unchangeable; } }; class X { int changeable[3]; int unchangeable[3]; Xproxy operator[](int i) { return Xproxy(changeable[i], unchangeable[i]) } };
So now when you call the operator[] on X, you get an Xproxy object that has references inside to both the changeable and unchangeable fields.
If you try to assign to Xproxy object it will invoke the operator= which assigns to the reference to the changeable. If you try to assign the Xproxy object to an int, it calls the cast operator which pulls from the unchangeable field.