Regarding on how does it work (as MSalters mentioned) this is just about incorrect naming.
Actually it shall be named void*
, of course.
But why does it work for int*
, const char*
etc (actually any pointer type, including pointer to user defined types)?
Well, I can suppose this is related to very interesting C++ exception handling issue - catch(void*)
exception handler actually catches any (cv-compatible) pointer type exceptions!
Example:
try
{
throw "Catch me if you can!";
}
catch(void* e)
{
// ...and I can!
std::cout << "Gotcha!" << std::endl;
}
Here we throw char*
(in Visual C++ char literals are char*
, not const char*
) and catch it by void*
. And it will work!
The answer can be found in C++ Holy Standard:
§15.3 Handling an exception
15.3.3 A handler is a match for an exception object of type E if
...
the handler is of type cv1 T* cv2 and E is a pointer type that can be converted to the type of the handler by either or both of
— a standard pointer conversion (4.10) not involving conversions to pointers to private or protected or ambiguous classes
...
And 4.10 says that standard pointer conversion includes conversion to void*
:
4.10.2 A prvalue of type “pointer to cv T,” where T is an object type, can be converted to a prvalue of type “pointer
to cv void”.
Note also that Visual Studio debugger works similar way, but not exactly this way. The difference is that it ignores cv-qualifiers. So void
in Exceptions dialog actually means any [any cv] void*
. Catch handlers will not ignore them:
try
{
struct Throwee {};
const Throwee* t = nullptr;
throw t;
}
catch(void* e)
{
// Will be missed
std::cout << "Gotcha!" << std::endl;
}
catch(const void* e)
{
// Will be catched
std::cout << "Gotcha const!" << std::endl;
}
throw 5;
). A short test reveals: that's not the case - looking forward to the answer...