【问题标题】:Fold expression within assertion compiles on some machines, but not on others断言中的折叠表达式在某些机器上编译,但在其他机器上不编译
【发布时间】:2018-10-30 19:33:46
【问题描述】:

我有以下代码(用于演示目的)应该断言所有参数都使用 C++17 折叠表达式计算为真。

#include <cassert>

template<typename... Ts>
void fn(Ts... ts)
{
    assert(ts && ...);
}

int main()
{
    fn(true, true, true);
    fn(true, true, false, true);
}

在 Coliru 上,它按预期工作;它不在我的机器上。我得到了错误

In file included from /usr/include/c++/8.2.1/cassert:44,
                 from foldexpr.cpp:1:
foldexpr.cpp: In function ‘void fn(Ts ...)’:
foldexpr.cpp:6:15: error: expected ‘)’ before ‘&&’ token
     assert(ts && ...);
               ^~
foldexpr.cpp:6:5: error: expected ‘;’ before ‘)’ token
     assert(ts && ...);
     ^~~~~~

使用 gcc 版本 8.2.1 20180831。在 Ubuntu 上使用 gcc 版本 5.4.0 20160609 我得到

In file included from /usr/include/c++/5/cassert:43:0,
                 from foldexpr.cpp:1:
foldexpr.cpp: In function ‘void fn(Ts ...)’:
foldexpr.cpp:6:18: error: expected primary-expression before ‘...’ token
     assert(ts && ...);
                  ^
foldexpr.cpp:6:18: error: expected ‘)’ before ‘...’ token
foldexpr.cpp:6:22: error: expected ‘)’ before ‘;’ token
     assert(ts && ...);
                      ^
foldexpr.cpp:6:22: error: parameter packs not expanded with ‘...’:
foldexpr.cpp:6:22: note:         ‘ts’

这是一个表格,其中列出了相应编译器版本的工作和不工作的地方。

| OS              | GCC               | Clang             |
|-----------------|-------------------|-------------------|
| Arch            | no (v8.2.1)       | no (v7.0.0)       |
| Ubuntu (Coliru) | yes (v8.1.0)      | yes (v5.0.0)      |
| Debian          | yes (v6.3.0)      | -                 |
| ? (Godbolt)     | no (all versions) | no (all versions) |

由于它的工作/失败如此随意,我觉得这是标准库的问题,并且默认情况下 clang 使用 libstdc++,我相信,这可以解释为什么它在系统上对两者都有效或无效。

这段代码应该编译吗?如果是,我该如何让它工作?如果不是,是否是编译器错误?

PS:在 Coliru 上我已经能够使用相当复杂的折叠表达式了,但是我没有在其他机器上尝试过其他的。

【问题讨论】:

    标签: c++ g++ c++17 clang++ fold-expression


    【解决方案1】:

    折叠表达式的形式必须为

    ( pack op ... )
    ( ... op pack )
    ( pack op ... op init )
    ( init op ... op pack ) 
    

    你的

    assert(ts && ...)
    

    没有遵循,它缺少括号。你需要

    assert((ts && ...))
    

    使其语法正确。

    【讨论】:

    • 非常有趣。所以assert 的一些实现似乎添加了额外的括号
    • @PostSelf 这是允许的。这是assert 的实现细节。让它在语法上正确,但应该使它在所有支持的平台上都能工作。如果没有,那么它确实是一个错误。
    • 解决办法是加括号? Lithp,我们来了!
    • @TimRandall 这是调试 101。在周围撒上()*&amp;,希望它能让它变得更好;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多