3

I have the following code that is (for demonstration purposes) supposed to assert that all arguments evaluate to true using C++17 fold expressions.

#include <cassert>

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

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

On Coliru it works as expected; it does not on my machine. I get the error

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 && ...);
     ^~~~~~

with gcc version 8.2.1 20180831. On Ubuntu with gcc version 5.4.0 20160609 I get

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’

Here is a table of where it worked and where it didn't with the corresponding compiler versions.

| 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) |

Since it works/fails so arbitrarily I feel like this is a problem with the standard library and clang by default uses libstdc++, I believe, which would explain why it either works or doesn't work for both on a system.

Should this code compile? If yes, how do I make it work? If no, is it a compiler bug?

PS: On Coliru I have been able to use quite complex folding expressions, but I have not tried others on other machines.

Post Self
  • 1,471
  • 2
  • 14
  • 34

1 Answers1

8

A fold expression must be in the form of

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

Your

assert(ts && ...)

Does not follow that, it is missing the enclosing parentheses. You need

assert((ts && ...))

to make it grammatically correct.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402