c++ - Clang 和二进制折叠表达式——空参数包的诅咒

标签 c++ clang compiler-bug c++17 fold-expression

特别是 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/

相关文章:

c++ - 为什么 'simplified' 代码没有向量化

objective-c - Swift: 'Int' 无法转换为 'ObjCBool'

c++ - 使用 C++ 更改 qml 文件中文本区域的文本

c++ - 为什么将 "pointer to pointer to non-const"转换为 "pointer to pointer to const"是不合法的

c++ - 是否还有理由在 C++ 代码中使用 `int`?

c++ - 速度关键系统的设计跟踪/日志

c++11 - libc++ 向量和字符串编译简单代码的异常规范实例化时出错

未修改的本地地址是否会在 setjmp/longjmp 中损坏?

c - 在 C 中遍历列表时,我是否看到了优化错误?

c# - 使用 Visual Studio 2010 编译时,覆盖泛型迭代器会导致 BadImageFormatException