Reputation: 55
There is a class like this:
class X {
public:
...
private:
int changeable[3];
int unchangeable[3];
};
And this is its desirable usage:
X x;
x[0] = 1; // here changeable[0] should be used
a = x[0]; // here unchangeable[0] should be used
Is there any way of defining operator[]
in class X
to implement that?
Upvotes: 3
Views: 280
Reputation: 20383
I think I have a "sort of" solution. It is not an exact solution to the problem asked, however, I believe, this is more of practical use.
The idea is simply that, a const X
variable would result in accessing unchangeable_
, a non-const X
variable would result in accessing changeable_
.
class X {
public:
const int & operator[]( int index ) const {
cout << __PRETTY_FUNCTION__ << " index = " << index << "\n";
return unchangeable_[ index ];
}
int & operator[]( int index ) {
cout << __PRETTY_FUNCTION__ << " index = " << index << "\n";
return changeable_[ index ];
}
private:
int changeable_[ 3 ];
int unchangeable_[ 3 ];
};
void foo( X const & x1 ) {
int a = x1[ 1 ]; // reading from x
}
int main() {
X x;
x[ 0 ] = 1; // writing to x
int a = x[ 1 ]; // reading from x
foo( x );
}
The output is:
int& X::operator[](int) index = 0
int& X::operator[](int) index = 1
const int& X::operator[](int) const index = 1
Upvotes: 0
Reputation: 3598
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.
Upvotes: 3
Reputation: 72271
Sort of, but you need to be sneaky.
class X {
private:
class XIndex;
public:
XIndex operator[](int);
//...
};
class X::XIndex {
public:
operator int() const;
void operator=(int val);
private:
friend class X;
XIndex(int* lvalue, int const* rvalue);
int* _lval;
int const* _rval;
// Disallow copy and assignment.
XIndex(const XIndex&);
XIndex& operator=(const XIndex&);
};
X::XIndex X::operator[](int i) {
// Check array bound?
return XIndex(&changeable[i], &unchangeable[i]);
}
// Implementation of X::XIndex methods is an exercise.
Note that if the x[num] expression appears anywhere other than immediately left of an = operator, the "rvalue" is used. You can also add operator+=
, operator*=
, etc. if you want.
Upvotes: 2