why can I not use the dummy parameter in postfix operator++ like someClassObject++5?

Viewed 351

I know I can use a dummy int in the postfix operator++ as someClassObject.operator++(5), but why can't use it like someClassObject++5? I am asking this because operator+ can be used like someClassObject1 + someClassObject2.

{
public:

    test(int x, string y) : x(x), y(y){}
    test() :x(0), y("") {};

    //skiping some code for copy constructor and assignment operator overload

    test operator++(int x)
    {
        test a(*this);
        a.x += x;
        ++(*this);
        return a;
    }

    friend ostream& operator<<(ostream& ost, const test& test)
    {
        ost << test.x << " , " << test.y;
        return ost;
    }


    int x;
    string y;
};

int main()
{
    test t1(5, "testing");
    int x = 10;
    cout << t1.operator++(x) << endl;
    //the above line of code works but the line below gives error.
    t1++x;
    return 0;
}

I was expecting both t1.operator++(5) and t1++5 would work in the same way.

2 Answers

Due to the maximal munch rule, the expression

t1++x

is parsed as

t1 ++ x

and grouped as

(t1 ++) x

This makes no sense; rather like t1 x makes no sense.

I know I can use a dummy int in the postfix operator++ as someClassObject.operator++(5), but why can't use it like someClassObject++5?

Because the Standard Says So™.

Due to how C++ code gets parsed and compiled, postfix ++ and -- work a bit different.

Let's have a look at the C++11 standard [draft].

13.5.1 Unary operators [over.unary]

[...] See 13.5.7 for an explanation of the postfix unary operators ++ and --.

Okay, so ++ and -- are considered unary operators (i.e. accepts one operand). Something like 1 ++ 2 implies that ++ is a binary operator (i.e. accepts two operands). But there is no binary ++ operator. The postfix ++ operator is to be overloaded like one, but it actually isn't resolved as one. Let's flip back a bit through the standard.

13.3.1.2 Operators in expressions [over.match.oper]

If either operand has a type that is a class or an enumeration, a user-defined operator function might be declared that implements this operator† or a user-defined conversion can be necessary to convert the operand to a type that is appropriate for a built-in operator. In this case, overload resolution is used to determine which operator function or built-in operator is to be invoked to implement the operator. Therefore, the operator notation is first transformed to the equivalent function-call notation as summarized in Table 11 (where @ denotes one of the operators covered in the specified subclause).

 Table 11 — Relationship between operator and function call notation 
Subclause  | Expression | As member function | As non-member function
                           [...]
13.5.2     | a@b        | (a).operator@(b)   | operator@ (a, b)
                           [...]
13.5.7     | a@         | (a).operator@(0)   | operator@ (a, 0)

(emphasis added)
† someClassObject is a class and a user-defined operator function (test operator++(int x)) is declared, so this particular clause applies to your case.

Firstly, I included the row with subclause 13.5.2 to clear any doubts. §13.5.2 deals with binary operators. But as we've established, there is no binary ++ operator in C++ and the only postfix ++ operator is an unary. So that row doesn't apply.

The last row is more interesting. According to this, postfix increment will be "transformed" from say, obj++ to obj.operator++(0). This means an int is already passed due to overload resolution.

Just for completeness, here's §13.5.7:

13.5.7 [over.inc]

The user-defined function called operator++ implements the prefix and postfix ++ operator. If this function is a member function with no parameters, or a non-member function with one parameter of class or enumeration type, it defines the prefix increment operator ++ for objects of that type. If the function is a member function with one parameter (which shall be of type int) or a non-member function with two parameters (the second of which shall be of type int), it defines the postfix increment operator ++ for objects of that type. When the postfix increment is called as a result of using the ++ operator, the int argument will have value zero.


I am asking this because operator+ can be used like someClassObject1 + someClassObject2.

+ can be both a unary and binary operator. That's why +2 and 1 + 2 are both valid expressions. But ++ is an unary operator (even though it's overloaded like a binary one).

Related