为啥不能将不完整的类型强制转换为 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?的主要内容,如果未能解决你的问题,请参考以下文章

C++|项目开发—强制类型转换回顾

C++|项目开发—强制类型转换回顾

为啥可以将切片分配给空接口但不能将其强制转换为相同的空接口

为啥不使用强制转换语法调用“operator void”?

强制类型转换规则

关于java中的short和int类型转换的问题