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