Home > database >  Understanding what (void) does when placed in front of a function call
Understanding what (void) does when placed in front of a function call

Time:10-15

My questions is:

Why is the (void) responsible to return a different value? What's exactly happening?

struct S {
  int operator,(int) { return 0; }
};
std::cout << (S(), 42) << '\n';           // prints '0'
std::cout << ((void) S(), 42) << '\n';    // prints '42'

CodePudding user response:

Problem here is that comma operator has been overloaded.

So first line:

(S(), 42)

Will invoke this custom overload of comma operator, since arguments are S and int which matches this overload. Note this version always returns 0 value.

In second line:

((void) S(), 42)

Your custom overload of comma operator doesn't match type passed, since first argument is type of void (casting is done). So build-in version of comma operator kicks in. This means that second argument will be returned. That it is why in second line 42 is printed.

Side note:

  • Yes C allows you to overload comma operator, but it is unusual and quite often treated as a bad practice. In many coding standards it is forbidden.

CodePudding user response:

(void) is performing explicit conversion (to void).

For the 1st case S(), 42, the S::operator, will be invoked on temporary S (i.e. S()) and return the value 0.

For the 2nd case, the temporary S is converted to void explicitly, so for (void) S(), 42 the built-in comma operator will be invoked instead, as the effect the 2nd operand 42 will be returned by comma operator and then printed out. (The 1st operand (void) S() is evaluated firstly and the result is discarded.)

The type, value, and value category of the result of the comma expression are exactly the type, value, and value category of the second operand

CodePudding user response:

The important thing to note in the second statement is that the cast has higher precedence over the comma operator ,. This means that the expression ((void) S(), 42) is actually grouped as(or equivalent to writing) (((void) S()), 42) due to operator precedence.

Thus in the second case, the temporary S() is first cast to void so that the resulting type is void. Now, since the custom overloaded S::operator,(int) is no longer viable(as it takes argument of type S and int), the built in operator, will be used with operands of type void(that was returned from the case you used) and 42 and it will return the rightmost operand 42. Hence the second statement print 42.

  •  Tags:  
  • c
  • Related