views:

129

answers:

2

What can I do when I need different job done, depending on the rval and lval type? Defining several overloads pop out with error 'operator = is ambiguous'.

Any ideas, or tips (links to tutorials), are much appreciated, since I've just today found out about operator overloading.

Thanks in advance!

EDIT:

Yes, I'd use C++0x since I have it available, just I don't see how would it impact on the code?

These are two cases in which I use it atm, if I get it well lval is different, so they are recognizable. The purpose is conversion to appropriate type.

int wrapint::operator=(int)
{
    return m_iCurrentNumber;
}

void wrapint::operator=(const int& rhs)
{
    m_iCurrentNumber = rhs;
}
+1  A: 

operator= is supposed to modify the left-hand value and the left-hand value has to be of the class type. The return value (normally *this) is mostly ignored, except when you chain assignments / other function calls (e.g a = b = c; where the result of b = c is assigned to a).

If you want to be able to assign a wrapint to a built-in int, then this can be achieved by defining a cast operator for wrapint

wrapint::operator int() const { return m_iCurrentNumber; }

Now wrapint will be implicitly converted to an int, when you try to assign one to an int.

int a;
wrapint w;
a = w;  //== a = w.operator int() 
visitor
+2  A: 

For wrapint = wrapint situation:

wrapint& wrapint::operator=(const wrapint& rhs)
{
    // test for equality of objects by equality of address in memory
    // other options should be considered depending on specific requirements
    if (this == &rhs) return *this;

    m_iCurrentNumber = rhs.m_iCurrentNumber;

    return *this;
}

I must say the above is a correct signature for an assignment operator. I think the signatures you provided are wrong, or at least I have never seen such a thing in my experience with C++.

If you want to convert from an int to a wrapint and the other way around then you have to provide the following:

1) from int to wrapint - a proper constructor that will allow implicit conversion from int; as a side note you should really make sure that the behavior is intended and within problem scope when working with such implicit conversions (take a look at C++'s explicit keyword for further "enlightenment")

2) from wrapint to int - a proper cast operator

Below is an example:

#include <iostream>

class wrapint
{ 
public:
   wrapint() : m_iCurrentNumber(0)
   { 

   }

   // allow implicit conversion from int
   // beware of this kind of conversions in most situations
   wrapint(int theInt) : m_iCurrentNumber(theInt)
   { 

   }

   wrapint(const wrapint& rhs) 
   {
    if (this != &rhs) 
        this->m_iCurrentNumber = rhs.m_iCurrentNumber; 
   }

   wrapint& operator=(const wrapint& rhs);

   operator int ()
   {
        return m_iCurrentNumber;
   }

 private:
     int m_iCurrentNumber;
 };

 wrapint& wrapint::operator=(const wrapint& rhs)
 {
     // test for equality of objects by equality of address in memory
     // other options should be considered depending on specific requirements
     if (this == &rhs) return *this;

     m_iCurrentNumber = rhs.m_iCurrentNumber;
     return *this;
 }

 using namespace std;

 int main()
 {
     // this will be initialized to 0
     wrapint theOne;
     // this will be 15
     wrapint theOtherOne = 15;

     cout << "The one: " << theOne << "\n";
     cout << "The other one: " << theOtherOne << "\n";

     theOne = theOtherOne;

     int foobar = theOne;
     // all should be 15
     cout << "The one: " << theOne << "\n";
     cout << "The other one: " << theOtherOne << "\n";
     cout << "The foobar: " << foobar << "\n";
     return 0;
 }
celavek
+1 After rereading the question about three times I think this is what the OP is after. BUT please consider adding a note that implicit conversions like this can often cause far more headaches than they solve.
Mark B
@Mark B noted and acted upon :) . Thanks
celavek
Found it out alone earlier today, still this covers the answer, thanks!
Johnny