特别是 Clang 3.6.0,目前由 Coliru 托管。
所有这些片段都是从以下位置调用的:
int main() {
foo();
std::cout << "\n----\n";
foo(1, 2, 3);
}
以下代码:
template <class... Args>
void foo(Args... args) {
std::cout << ... << args;
}
触发以下编译错误:
main.cpp:7:17: error: expected ';' after expression
std::cout << ... << args;
^
;
main.cpp:7:15: error: expected expression
std::cout << ... << args;
^
所以我尝试在表达式周围加上括号:
(std::cout << ... << args);
它可以工作,但会触发警告:
main.cpp:7:6: warning: expression result unused [-Wunused-value]
(std::cout << ... << args);
^~~~~~~~~
main.cpp:11:5: note: in instantiation of function template specialization 'foo<>' requested here
foo();
^
所以我尝试通过将函数样式强制转换为 void
来丢弃表达式的值:
void(std::cout << ... << args);
但是:
main.cpp:7:20: error: expected ')'
void(std::cout << ... << args);
^
main.cpp:7:9: note: to match this '('
void(std::cout << ... << args);
^
我也尝试了 static_cast
,结果相同。
所以我尝试使用 C-cast 代替:
(void)(std::cout << ... << args);
然后:
main.cpp:6:18: warning: unused parameter 'args' [-Wunused-parameter]
void foo(Args... args) {
^
...而我的输出只是 ----
: foo(1, 2, 3);
不再输出了!
Clang 是不是被 future 标准的邪恶力量诅咒了,它有错误,还是现在我的椅子上有问题?
最佳答案
在转换为 void
时需要额外的一组括号使用功能符号强制转换,否则括号被认为是强制转换表达式而不是折叠表达式的一部分。 fold expression syntax本身需要一组括号。
以下所有操作都不会产生任何警告:
void((std::cout << ... << args));
(void)((std::cout << ... << args));
或者直接调用ostream
成员函数以避免未使用的结果警告
(std::cout << ... << args).flush();
作为 T.C.在下面的评论中提到 (void)(std::cout << ... << args);
的行为似乎是一个铿锵的错误。转换符号的语法在 5.4 [expr.cast]
cast-expression:
unary-expression
( type-id ) cast-expression
由于括号不需要作为强制转换表达式的一部分,因此该用法不应产生警告,更重要的是,它应该会导致打印参数。
关于c++ - Clang 和二进制折叠表达式——空参数包的诅咒,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31972608/