将异常编译器错误强制转换为void

Unusual compiler error casting to void?

本文关键字:转换 void 异常 编译器 错误      更新时间:2023-10-16

我正在为我正在教的一门课编写一份基于C++的作业。我有一个函数正在导出给学生,我希望他们在课程的各个阶段调用该函数,这样,在评分过程中,我们可以拦截这些调用,以确保他们在正确的时间做正确的事情。我不希望这些代码在提供的启动文件中做任何事情,所以我只是给函数一个主体,它只有一系列语句,将所有参数强制转换为void,以抑制编译器对未使用参数的警告。在这样做的过程中,我遇到了一个前所未有的异常编译器错误,在这个网站上搜索也没有发现任何帮助。

这个简化的测试用例可以最好地说明错误:

void iDontUseMyArguments(int a, int b) {
(void) a;    // Explicit cast to void - totally fine!
(void) b;
}
void iDontEither(int a, int b) {
(void) a, b;  // Comma expression casted to void, though technically
// b isn't casted to void!
}
void norDoI(int a, int b) {
void(a, b);   // ERROR! No idea why this isn't okay.
}
void meNeither(int a, int b) {
(void)(a, b); // Comma expression casted to void - totally fine!
}
void jumpOnBandwagon(int a, int b) {
void((a, b)); // Comma expression casted to void - totally fine!
}

正如您所看到的,大多数编译都很好。问题就在这个:

void(a, b);

这会触发以下错误:

prog.cpp: In function 'void norDoI(int, int)':
prog.cpp:11:11: error: expression list treated as compound expression in functional cast [-fpermissive]
void(a, b);
^

我从来没有遇到过这个错误消息,所以我不确定这是想告诉我什么。

背后的意图

void(a, b);

是一个包含ab的逗号表达式,然后使用函数样式转换将其转换为类型void。正如你所看到的,以下变体都有效:

(void)(a, b);
void((a, b));

我怀疑这可能与Most Vexing Parse有关,这被解释为一个声明,但我得到的特定错误似乎与此不匹配。

我的问题如下:

  1. 为什么这个代码不合法
  2. 编译器认为我要做什么
  3. 为什么这些其他变体是合法的

给定此结构:

struct S {
S(int, int) {}
};

S(1, 2)是什么意思?

答:这意味着您根据值12构造了一个类型为S的对象。


给定此函数模板:

template <typename T> T f() { return T(1, 2); }

T(1, 2)是什么意思?

答:这意味着您根据值12构造一个类型为T的对象,例如,如果T是第一个问题中的类型S,则这是可能的。


给定相同的函数模板,那么f<void>()意味着什么?

答:它试图从两个值12构造一个单独的void值。这失败了,因为只有单个值可以转换为void


T恰好是void时,void(1, 2)T(1, 2)有什么不同吗?

答:不,意思完全一样,这就是为什么它是一个错误。

查看文档,我认为您违反了转换案例规则(#3)之一:

如果括号中有多个表达式,则new_type必须是具有适当声明的构造函数的类。此表达式是new_type类型的prvalue,指定临时(直到C++17),其结果对象(从C++17开始)直接用表达式初始化。

在第void(a, b);行中,编译器"认为"您正试图使用类型作为函数名,因此它给出了一个错误。

其他情况是类型铸造。。。