Why does the following code give the following error?
Why does the type need to be complete in order to be casted to void
?
struct Incomplete;
class Class
{
virtual void foo(Incomplete &incomplete)
{
(void) incomplete;
throw std::logic_error("not implemented");
}
};
Error:
error C2027: use of undefined type 'Incomplete'
see declaration of 'Incomplete'
It's a change between C and C++, where Microsoft previously implemented the C rules. As noted in remyabel's answer, that has since been fixed.
In C, a cast to void
, or simply using an expression as a statement by itself (as in incomplete;
), still involves the lvalue-to-rvalue conversion. C calls it slightly differently, but it's the same conversion.
In C++, a cast to void
, or simply using an expression as a statement by itself doesn't involve the lvalue-to-rvalue conversion. This is needed because C++ makes assignment operators return lvalues, so if the lvalue-to-rvalue conversion were applied, then
volatile int i;
i = 1;
would not merely store, it would also immediately load afterwards.
The lvalue-to-rvalue conversion requires a complete type, even if the value is then discarded, since otherwise, it's impossible to know how many bytes should be read.
I don't see anything prohibiting this, quoting N4140:
§5.4/4 The conversions performed by
[...]
— a static_cast
(5.2.9),
[...]
can be performed using the cast notation of explicit type conversion.
§5.2.9/5 Otherwise, the static_cast
shall perform one of the
conversions listed below. No other conversion shall be performed
explicitly using a static_cast
.
§5.2.9/6 Any expression can be explicitly converted to type cv void,
in which case it becomes a discarded-value expression (Clause 5).
[...]
It's most likely a bug as tested on Rextester, an online VS2013 compiler, but compiles in rise4fun, Microsoft's online compiler which is bleeding edge.