2016-11-17 2 views
4

При попытке оценить оператор запятой с static_assert в качестве аргумента компиляции не удаетсяComma оператор с static_assert()

void fvoid() {} 

int main() { 
    int a = (1, 2); // a=2 
    int b = (fvoid(), 3); // b=3 

    int d = (, 5); 
    //  ^
    // error: expected primary-expression before ',' token. OK 

    int c = (static_assert(true), 4); 
    //  ^~~~~~~~~~~~~ 
    // error: expected primary-expression before 'static_assert'. Why? 
} 

Похоже, что static_assert() даже не постановляет void после компиляции. Мне не удалось найти что-либо по этому поводу в стандарте. Есть ли способ использовать его с помощью оператора запятой или использовать его в соответствии с другим выражением (без точки с запятой)?

+0

Просто любопытно: почему вы хотите использовать его с оператором запятая? – Rakete1111

+0

@ Rakete1111 в некотором состоянии макрос, который обычно возвращает значение, должен терпеть статическое утверждение, но все же он должен быть разрешен к значению, поэтому компилятор не генерирует избыточные ошибки. – teivaz

+1

Имеет смысл, и вы можете захотеть изменить название, так как это совсем другой вопрос, который не имеет никакого отношения к вашему актуальному вопросу. – Rakete1111

ответ

5

Нет, не существует. Для грамматики языка требуется точка с запятой в конце статического утверждения .

N4140 § 7 [dcl.dcl]/1

static_assert декларация:

static_assert (постоянное выражение, строка-буквальным);

3

Есть ли способ, чтобы использовать его с оператором запятой или использовать его в соответствии с другим выражением (без запятой)?

Как уже упоминалось в других ответах, вы не можете избежать использования точки с запятой при работе с static_assert.
Во всяком случае, вы можете обернуть его в лямбда, как это следует и по-прежнему использовать его как-то с оператором запятая:

int main() { 
    int c = ([]{ static_assert(true, "!"); }(), 4); 
} 

Вероятно, вы хотите испытать что-то более усложненный, чем true.
В этом случае вам нужно обойти (допустим) ограничения текущего определения лямбда (для которого не выполняется ни захват, ни передача в качестве аргумента, которое имеет значение boolean value).
Шаблон функции с аргументом шаблона непигового типа может выполнять эту работу. В качестве примера:

template<bool b> 
void f() { 
    int c = ([](){ static_assert(b, "!"); }(), 4); 
    // ... 
} 

После оптимизировано, полученный код, который использует лямбда не отличается, что многое (вы можете легко проверить его на godbolt, используя эти минимальные примеры).

+0

Этот код также использует краткие выражения для краткости. 'template void f() { ([]() {static_assert (b,"! ");}(), ...); } '}' } ' Расширение пакета параметров, похоже, не работает в gcc и работает в clang и msvc, я полагаюсь на неопределенное поведение или что-то в этом роде или это просто ошибка на gcc? –

+0

@PedroDavid На самом деле это похоже на ошибку GCC. Это стоит того, чтобы открыть проблему, если она не существует. Во всяком случае, я бы сделал это в C++ 17: 'static_assert ((b && ...),"! ");'. [Он отлично работает и с GCC] (https://wandbox.org/permlink/x3A2RZ5lRvceLezO). Не нужно обертывать его в лямбду. – skypjack

1

Вы можете просто обернуть его в блоке:

int c = ({ static_assert(true); }, 4); 
Смежные вопросы