为啥不能将不完整的类型强制转换为 void?
Posted
技术标签:
【中文标题】为啥不能将不完整的类型强制转换为 void?【英文标题】:Why can't an incomplete type be casted to void?为什么不能将不完整的类型强制转换为 void? 【发布时间】:2015-05-24 17:07:18 【问题描述】:为什么下面的代码会报如下错误?
为什么类型需要完整才能转换为void
?
struct Incomplete;
class Class
virtual void foo(Incomplete &incomplete)
(void) incomplete;
throw std::logic_error("not implemented");
;
错误:
error C2027: use of undefined type 'Incomplete'
see declaration of 'Incomplete'
【问题讨论】:
为什么会是更有趣的问题。只需改用(void)&incomplete
。
FWIW、GCC 和 clang 没有任何问题。
在 VS2013 中不编译,但在 Microsoft's online compiler 中编译。所以这可能只是一个错误。
有趣。你甚至不需要投到void
。试试void foo(Incomplete &incomplete) incomplete;
,它会给你同样的错误。
进一步表明这似乎是编译器的一个错误区域:尝试声明一个 Incomplete
数组,例如Incomplete x[1];
上面写着 error C2148: total size of array must not exceed 0x7fffffff bytes
,对于 GCC 所称的 elements of array 'Incomplete x [1]' have incomplete type
,这是一条非常奇怪的消息。
【参考方案1】:
这是 C 和 C++ 之间的变化,微软之前在其中实施了 C 规则。正如 remyabel 的回答中指出的那样,这已得到修复。
在 C 中,转换为 void
,或者只是将表达式本身用作语句(如在 incomplete;
中),仍然涉及左值到右值的转换。 C 对它的称呼略有不同,但它是相同的转换。
在 C++ 中,转换为 void
或仅使用表达式作为语句本身并不涉及左值到右值的转换。这是必需的,因为 C++ 使赋值运算符返回左值,所以如果应用了左值到右值的转换,那么
volatile int i;
i = 1;
不仅会存储,还会在之后立即加载。
左值到右值的转换需要一个完整的类型,即使该值随后被丢弃,否则无法知道应该读取多少字节。
【讨论】:
【参考方案2】:引用 N4140,我没有看到任何禁止这样做的内容:
§5.4/4 执行的转换
[...]
——
static_cast
(5.2.9),[...]
可以使用显式类型转换的强制转换表示法来执行。
§5.2.9/5 否则,
static_cast
应执行以下操作之一 下面列出的转换。不得进行其他转换 显式使用static_cast
。§5.2.9/6 任何表达式都可以显式转换为 cv void 类型, 在这种情况下,它变成了丢弃值表达式(第 5 条)。 [...]
这很可能是在 Rextester(一个在线 VS2013 编译器)上测试过的错误,但在 rise4fun(微软最前沿的在线编译器)中编译。
【讨论】:
以上是关于为啥不能将不完整的类型强制转换为 void?的主要内容,如果未能解决你的问题,请参考以下文章