开发者

Why myClassObj++++ doesn't incur a compile error : '++' needs l-value just as buildin type do?

Why myint++++ compiles fine with VS2008 compiler and gcc 3.42 compiler ?? I was expecting compiler say need lvalue, example see below.

struct MyInt
{
    MyInt(int i):m_i(i){}

    MyInt& operator++() //return reference,  return a lvalue
    {
        m_i += 1;
        return *this;
    }

    //operator++ need it's operand to be a modifiable lvalue
    MyInt operator++(开发者_Go百科int)//return a copy,  return a rvalue
    {
        MyInt tem(*this);
        ++(*this);
        return tem;
    }

    int     m_i;
};

int main()
{
    //control: the buildin type int
    int i(0);
    ++++i;  //compile ok
    //i++++; //compile error :'++' needs l-value, this is expected

    //compare 
    MyInt  myint(1);
    ++++myint;//compile ok
    myint++++;//expecting compiler say need lvalue , but compiled fine !? why ??
}


No, overloaded operators are not operators - they're functions. So GCC is correct to accept that.

myobj++++; is equivalent to myobj.operator++(0).operator++(0); Caling a member function (including overloaded operator) on a temprorary object of class type is allowed.


Because for user-defined types, operator overloads are literally just function calls, and so obey the semantics of function calls.


If you want to emulate the built-in behaviour there’s actually a very simple solution: make the return value const:

MyInt const operator++(int) { … }

A few years back there was a debate over whether user-defined operators should exactly model the built-in behaviour. I’m not sure which school of thought currently has the upper hand, but making the return type of operator++(int) const was a way of achieving this.


In the end, MyInt::operator++(int) is just another method. The same rules apply. Since you can call methods on rvalues, you can call operator++(int) on rvalues.


myint++ returns something similar to MyInt(2). So, it's similar to doing MyInt(2)++. A temporary class is created in the operator++ function and you're incrementing the temporary class. After it's returned, it's deleted as soon as the next statement finishes (here, it's second ++ operator).


The issue is that the requirements of the postincrement operator for integral types and for user defined types are different. In particular a user defined postincrement operator implemented as a member function allow the use of rvalues.

If you had implemented the operator as a free function:

MyInt operator++(MyInt [const][&] x, int)

Then the requirements of that particular operator would be those extracted from the actual signature. If the first argument is taken by value, then it accepts rvalues directly, if it takes the argument by const & then it accepts rvalues if the copy constructor is accessible, if the argument is taken by non constant & then that operator will require lvalues.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜