Re: user-defined op= for type with reference member
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:
int i = 1;
IntByRef ibr(i);
ibr = 2;
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':-)
Regards
Paul Bibbings