Re: const correct member variable access thru function?
patrik.kahari@googlemail.com wrote:
The proper way to do it (IMO) would be to use a proxy class that
would know whether it's on the right or on the left side of the
assignment op. It's not as simple as introducing two overloaded
functions, like here:
Thanks, I cant believe i did not think of overloading..
because in this case if 'A' is non-const, then the non-const version
will be called if you use it in an expression (even though you're not
trying to assign to it):
That is interseting. So if I wanted to log read and write access to
the variable then overloading would not work.. hmm, I had a go at
making a proxy object emulating the variable, instead of having
functions emulating the variable. The same problem seems to creep up
though. That is, if Z is a non const object and I do a 'int tmp =
z.x;' then the non const assignment operator is called even though
this is a "read only" operation. Anyone got any tips or links to
related threads?
Example code (take 2):
template <class T>
struct Proxy {
public:
Proxy(T &x): x_ref_(x) {} //init ref
//assignment operator..
Proxy<T>& operator = (const T& rhs) {x_ref_ = rhs; /*cout<<"non-const
lhs";*/ return *this;}
//conversion operator..
operator T& () { /*cout<<"non-const rhs";*/ return x_ref_; }
operator const T& () const { /*cout<<"const rhs";*/ return x_ref_; }
private:
T &x_ref_;
};
struct A{
public:
int x;
};
struct Z {
private:
int x_;
public:
Proxy<int> x;
Z(): x_(0), x(x_) {;}
};
void main() {
int tmp;
A a = A();
a.x = 1;
tmp = a.x;
const A a_const = A();
tmp = a_const.x;
//---//
Z z = Z();
z.x = 1;
//tmp = z.x; // error C2593: 'operator =' is ambiguous. // ehh!?
{
Z z = Z();
z.x = 1;
int tmp = z.x; // calls non-const operator=() // calling non const
even though this is read only !?
}
{
const Z z_const = Z();
int tmp = z_const.x; // calls const operator =
}
}
OK, I don't have related threads, but here is what I managed to whip
up in ten minutes or so:
class A
{
int x_;
void change_x_value_to(int x) { x_ = x; }
int get_x_value() const { return x_; }
public:
A() : x_(666) {}
struct x_proxy
{
A const& a;
bool canchange;
x_proxy(A& a) : a(a), canchange(true) {}
x_proxy(A const& a) : a(a), canchange(false) {}
x_proxy& operator =(int i) {
if (!canchange) throw "cannot change a constant object";
const_cast<A&>(a).change_x_value_to(i);
return *this;
}
operator int() const { return a.get_x_value(); }
};
x_proxy x() { return x_proxy(*this); }
x_proxy x() const { return x_proxy(*this); }
};
int main ()
{
A a;
A const ca;
a.x() = 42;
int b, cb;
b = a.x();
cb = ca.x();
try {
ca.x() = 77;
}
catch (...) {
;
}
return 0;
}
Disclaimer: I didn't test it with all compilers avaiable to me,
and this is for illustration only, probably contains some big
errors I've missed.
It does not have a proper const checking for 'ca.x() = 77;', for
example, it can be achieved by introducing a sibling proxy to
'x_proxy', name it 'x_const_proxy', which should be returned
from the 'x' member of a constant object. I'll leave it for you
to implement.
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]