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

Que*_*tin 12 c++ clang compiler-bug fold-expression c++17

特别是Clang 3.6.0,目前由Coliru主持.

所有这些片段都来自:

int main() {
    foo();
    std::cout << "\n----\n";
    foo(1, 2, 3);
}
Run Code Online (Sandbox Code Playgroud)

以下代码:

template <class... Args>
void foo(Args... args) {
    std::cout << ... << args;
}
Run Code Online (Sandbox Code Playgroud)

触发以下编译错误:

main.cpp:7:17: error: expected ';' after expression
    std::cout << ... << args;
                ^
                ;
main.cpp:7:15: error: expected expression
    std::cout << ... << args;
              ^
Run Code Online (Sandbox Code Playgroud)

所以我试着在表达式周围添加括号:

(std::cout << ... << args);
Run Code Online (Sandbox Code Playgroud)

它有效,但会触发警告:

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();
    ^
Run Code Online (Sandbox Code Playgroud)

所以我试图通过函数样式转换来丢弃表达式的值void:

void(std::cout << ... << args);
Run Code Online (Sandbox Code Playgroud)

但是:

main.cpp:7:20: error: expected ')'
    void(std::cout << ... << args);
                   ^
main.cpp:7:9: note: to match this '('
    void(std::cout << ... << args);
        ^
Run Code Online (Sandbox Code Playgroud)

static_cast为了同样的结果,我也试过了.

所以我尝试用C-cast代替:

(void)(std::cout << ... << args);
Run Code Online (Sandbox Code Playgroud)

但是之后 :

main.cpp:6:18: warning: unused parameter 'args' [-Wunused-parameter]
void foo(Args... args) {
                 ^
Run Code Online (Sandbox Code Playgroud)

...而且我的输出只是----:foo(1, 2, 3);不再输出了!

Clang是否受到来自未来标准的邪恶力量的诅咒,它是否有虫子,或者现在坐在我的椅子上的问题是什么?

Pra*_*ian 11

void使用功能表示法转换时,您需要一组额外的括号,否则括号被视为转换表达式的一部分而不是折叠表达式.的倍的表达语法本身需要一组括号.

以下所有工作均未发出任何警告:

void((std::cout << ... << args));
(void)((std::cout << ... << args));
Run Code Online (Sandbox Code Playgroud)

或者只是调用一些ostream成员函数来避免未使用的结果警告

(std::cout << ... << args).flush();
Run Code Online (Sandbox Code Playgroud)

正如TC在下面的评论中提到的那样,行为(void)(std::cout << ... << args);似乎是一个铿锵的错误.强制转换表示法的语法在5.4 [expr.cast]中指定

cast-expression:
  unary-expression
  (type-id)cast-expression

由于括号不是铸造表达式的一部分,因此该用法不应产生警告,更重要的是,它应该导致打印参数.

  • 我不明白为什么`(void)(std :: cout << ... << args);`不起作用.这部分看起来像是一个错误. (4认同)