【问题标题】: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,这是一条非常奇怪的消息。

标签: c++ void 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(微软最前沿的在线编译器)中编译。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-07
      • 2012-03-06
      • 1970-01-01
      • 1970-01-01
      • 2017-07-11
      • 1970-01-01
      相关资源
      最近更新 更多