Выражение сгиба в утверждении компилируется на некоторых машинах, но не на других - PullRequest
0 голосов
/ 30 октября 2018

У меня есть следующий код, который (для демонстрационных целей) должен утверждать, что все аргументы имеют значение true, используя C ++ 17-кратные выражения.

#include <cassert>

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

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

На Колиру это работает как положено; это не на моей машине. Я получаю ошибку

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 мне удалось использовать довольно сложные выражения свёртывания, но я не пробовал другие на других машинах.

1 Ответ

0 голосов
/ 30 октября 2018

Складное выражение должно быть в форме

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

Ваш

assert(ts && ...)

Из этого не следует, в нем отсутствуют заключающие скобки. Вам нужно

assert((ts && ...))

, чтобы сделать это грамматически правильным.

...