Re: user-defined op= for type with reference member
Paul Bibbings <paul_bibbings@googlemail.com> wrote:
Francesco S. Carta wrote:
I'm not so sure whether the following could come interesting in this
case (nothing special for the most experienced ones, I suppose): it is
possible to store the reference as a pointer and create a "resettable
reference" in either of the following ways:
-------
#include<iostream>
using namespace std;
class IntByRef {
public:
explicit IntByRef(int& i) : ptr(&i) {};
operator int&() {
return *ptr;
}
int& operator=(int& i) {
ptr=&i;
return *ptr;
}
private:
int* ptr;
};
int main()
{
int local = 8;
IntByRef ibr(local);
cout<< ibr<< endl; // prints 8
local = 10;
cout<< ibr<< endl; // prints 10
int local2 = 42;
ibr = local2;
cout<< ibr<< endl; // prints 42
int& intref = ibr;
++ibr;
ibr *= 2;
ibr -= 8;
cout<< intref<< endl; // prints 78;
return 0;
}
-------
-------
#include<iostream>
using namespace std;
class SimplerIntByRef {
public:
SimplerIntByRef (int& i) : ptr(&i) {};
operator int&() {
return *ptr;
}
private:
int* ptr;
};
int main()
{
int local = 8;
SimplerIntByRef ibr(local);
cout<< ibr<< endl; // prints 8
local = 10;
cout<< ibr<< endl; // prints 10
int local2 = 42;
ibr = local2;
cout<< ibr<< endl; // prints 42
int& intref = ibr;
++ibr;
ibr *= 2;
ibr -= 8;
cout<< intref<< endl; // prints 78;
return 0;
}
-------
main() is practically identical for both cases, you can apply all
combined operator+equals to an IntByRef as well as all pre and post
increment/decrement, the only thing that you can't assign to it is a
constant or a temporary (that would be a plain rvalue) - by the means
of using operator= or by using the implicit ctor in the simpler case.
You can only (re)assign it to "point" to another (non-const) variable.
Modulo mistakes and misunderstandings as usual, I'm ready to have my
"view" fixed :-)
Personally, I cannot see what the point would be of class modelling a reference,
albeit a reseatable one, that didn't permit the simple assignment:
Actually, I didn't speculate that much about the uses of my class. We
could eventually consider it something like a read-only, only that it
isn't... read on...
int i = 1;
IntByRef ibr(i);
ibr = 2;
Yes, that last line would be forbidden with my class and the compiler
would complain, as if it were read-only - only that the simple
assignment with an actual lvalue would reseat the reference, and that
would make it not read-only - not look like a read-only, that would be
misleading... read on...
For myself, I would have the assignment operators assign *values*, and have the
reseating required to be done explicitly. Something like:
template<typename T>
class ReseatableRef
{
ReseatableRef(T& t): t_ptr(&t) { }
ReseatableRef& operator=(const T& t) // value assignment
{
*t_ptr = t;
return *this;
}
ReseatableRef& operator=(const ReseatableRef& other) // ditto!!!
{
*t_ptr = *other.t_ptr;
return *this;
}
ReseatableRef& reseat(T& t)
{
t_ptr =&t;
return *this;
}
operator T&() { return *t_ptr; }
operator T() const { return *t_ptr; }
T * operator&() const { return t_ptr; }
private:
T *t_ptr;
};
int main()
{
int local = 8;
iref_t ibr(local);
std::cout<< "1: ibr = "<< ibr<< '\n';
local = 10;
std::cout<< "2: ibr = "<< ibr<< '\n';
ibr = 42; // !!!
std::cout<< "3: ibr = "<< ibr<< '\n';
local = 0;
int local2 = 1;
ibr.reseat(local2);
std::cout<< "4: ibr = "<< ibr<< '\n';
int& local22 = local2;
int& local222 = local22;
std::cout<< "&local2 = "<< &local2<< '\n';
std::cout<< "&local22 = "<< &local22<< '\n';
std::cout<< "&local222 = "<< &local222<< '\n';
iref_t ibr2(ibr);
iref_t ibr3(ibr2);
std::cout<< "&ibr = "<< &ibr<< '\n';
std::cout<< "&ibr2 = "<< &ibr2<< '\n';
std::cout<< "&ibr3 = "<< &ibr3<< '\n';
}
/**
* Output:
* 1: ibr = 8
* 2: ibr = 10
* 3: ibr = 42
* 4: ibr = 1
*&local2 = 0x22cd08
*&local22 = 0x22cd08
*&local222 = 0x22cd08
*&ibr = 0x22cd08
*&ibr2 = 0x22cd08
*&ibr3 = 0x22cd08
*/
I think that this would be closer to the behaviour of an ordinary reference over
all, with the *addition* that it can be reseated. Of course, it also allows for
the creation of a `reference to a reference':-)
Definitely better, thanks for pointing that out.
It's not that rare to see me posting code out of the top of my head,
just for the sake of explaining my point about something - luckily, some
kindhearted ones happen to pass and fix, extend or somehow else modify
my code and make it something (more) usable :-)
--
FSC
http://userscripts.org/scripts/show/59948