不寻常的编译器错误转换为无效?
Unusual compiler error casting to void?
我正在为我正在教的 class 整理一个基于 C++ 的作业。我有一个函数要导出给学生,我希望他们在程序的不同点调用它,以便在评分期间,我们可以拦截这些调用以确保他们在正确的时间做正确的事情.我不希望该代码在提供的起始文件中执行任何操作,因此我只为该函数提供了一个主体,该主体仅包含一系列语句,这些语句将所有参数强制转换为 void
以抑制编译器关于未使用参数的警告。在这样做的过程中,我 运行 遇到了一个我以前从未见过的不寻常的编译器错误,并且对该站点的搜索没有找到任何有用的信息。
错误可以通过 this reduced test case:
得到最好的例证
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);
是一个包含 a
和 b
的逗号表达式,然后使用函数式转换将其转换为类型 void
。如您所见,以下变体都有效:
(void)(a, b);
void((a, b));
我怀疑这可能与 Most Vexing Parse 有关,这被解释为声明,但我遇到的特定错误似乎与此不符。
我的问题如下:
- 为什么这个代码不合法?
- 编译器认为我要做什么?
- 为什么这些其他变体是合法的?
在第 void(a, b);
编译器 "think" 行中,您试图将类型用作函数名称,因此它给出了错误。
其他情况是类型转换...
查看 documentation 我想您违反了转换案例规则之一 (#3):
If there are more than one expression in parentheses, new_type must be a class with a suitably declared constructor. This expression is a prvalue of type new_type designating a temporary (until C++17)whose result object is (since C++17) direct-initialized with expressions.
鉴于此结构:
struct S {
S(int, int) {}
};
S(1, 2)
是什么意思?
答案:这意味着您从值 1
和 2
.
构造一个类型 S
的对象
给出这个函数模板:
template <typename T> T f() { return T(1, 2); }
T(1, 2)
是什么意思?
答案:这意味着您从值 1
和 2
构造一个类型 T
的对象,如果 T
是类型 S
来自第一个问题。
给定相同的函数模板,那么 f<void>()
是什么意思?
答案:它试图从 1
和 2
这两个值构造一个 void
值。这失败了,因为只能将单个值转换为 void
.
当 T
恰好是 void
时,void(1, 2)
与 T(1, 2)
有什么不同吗?
答案:不,这两个意思完全一样,这就是错误的原因。
我正在为我正在教的 class 整理一个基于 C++ 的作业。我有一个函数要导出给学生,我希望他们在程序的不同点调用它,以便在评分期间,我们可以拦截这些调用以确保他们在正确的时间做正确的事情.我不希望该代码在提供的起始文件中执行任何操作,因此我只为该函数提供了一个主体,该主体仅包含一系列语句,这些语句将所有参数强制转换为 void
以抑制编译器关于未使用参数的警告。在这样做的过程中,我 运行 遇到了一个我以前从未见过的不寻常的编译器错误,并且对该站点的搜索没有找到任何有用的信息。
错误可以通过 this reduced test case:
得到最好的例证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);
是一个包含 a
和 b
的逗号表达式,然后使用函数式转换将其转换为类型 void
。如您所见,以下变体都有效:
(void)(a, b);
void((a, b));
我怀疑这可能与 Most Vexing Parse 有关,这被解释为声明,但我遇到的特定错误似乎与此不符。
我的问题如下:
- 为什么这个代码不合法?
- 编译器认为我要做什么?
- 为什么这些其他变体是合法的?
在第 void(a, b);
编译器 "think" 行中,您试图将类型用作函数名称,因此它给出了错误。
其他情况是类型转换...
查看 documentation 我想您违反了转换案例规则之一 (#3):
If there are more than one expression in parentheses, new_type must be a class with a suitably declared constructor. This expression is a prvalue of type new_type designating a temporary (until C++17)whose result object is (since C++17) direct-initialized with expressions.
鉴于此结构:
struct S {
S(int, int) {}
};
S(1, 2)
是什么意思?
答案:这意味着您从值 1
和 2
.
S
的对象
给出这个函数模板:
template <typename T> T f() { return T(1, 2); }
T(1, 2)
是什么意思?
答案:这意味着您从值 1
和 2
构造一个类型 T
的对象,如果 T
是类型 S
来自第一个问题。
给定相同的函数模板,那么 f<void>()
是什么意思?
答案:它试图从 1
和 2
这两个值构造一个 void
值。这失败了,因为只能将单个值转换为 void
.
当 T
恰好是 void
时,void(1, 2)
与 T(1, 2)
有什么不同吗?
答案:不,这两个意思完全一样,这就是错误的原因。