Why does the following program
#include <iostream>
struct C
{
operator int()
{
std::cout << "C::operator int()" << std::endl;
return 0;
}
operator void()
{
std::cout << "C::operator void()" << std::endl;
}
};
int main()
{
C c;
(int)c;
(void)c;
// this does run the function:
// c.operator void();
}
output this
C::operator int()
instead of this?
C::operator int()
C::operator void()
Live demo at coliru.
The immediate answer, as always, is "because the standard says so".
C++11 standard, ยง 12.3.2
A conversion function is never used to convert a (possibly cv-qualified) object to the (possibly cv-qualified) same object type (or a reference to it), to a (possibly cv-qualified) base class of that type (or a reference to it), or to (possibly cv-qualified) void.
So why does the standard say so? What is the benefit of making void conversion functions a special case?
Additional exposition is in footnote 116:
These conversions are considered as standard conversions for the purposes of overload resolution (13.3.3.1, 13.3.3.1.4) and therefore initialization (8.5) and explicit casts (5.2.9). A conversion to void does not invoke any conversion function (5.2.9). Even though never directly called to perform a conversion, such conversion functions can be declared and can potentially be reached through a call to a virtual conversion function in a base class.
I've only ever used (void)
to silence compiler warnings about unused variables. It looks like that's essentially what others use it for too.
Why cast unused return values to void?
If void
conversion functions followed the typical conversion function rules it might allow for surprises but that's true of any conversion function with side effects and creating those surprises would be at the discretion of the programmer.