逗号运算符与 static_assert()

问题描述 投票:0回答:4

尝试使用

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
。我没有在标准中找到任何与此相关的内容。有没有办法将它与逗号运算符一起使用或与其他表达式(不带分号)一起使用?

c++ runtime static-assert
4个回答
8
投票

不,没有。语言语法要求静态断言末尾有一个分号声明

N4140 §7 [dcl.dcl]/1

static_assert-声明

static_assert (
常量表达式 , 字符串文字
)
;


5
投票

有没有办法将它与逗号运算符一起使用或与其他表达式(不带分号)一起使用?

正如其他答案中已经提到的,在处理

static_assert
时不能避免使用分号。
无论如何,您可以将其包装在 lambda 中,如下所示,并且仍然以某种方式与逗号运算符一起使用它:

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

您可能想测试比

true
更复杂的东西。
在这种情况下,您必须解决当前 lambda 定义的(让我说)限制(对于该定义,布尔值既不能捕获也不能作为参数传递)。
具有非类型模板参数的函数模板可以完成这项工作。举个例子:

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

优化后,使用 lambda 的生成代码不会有太大差异(您可以使用这些最小示例在 godbolt 上轻松检查它)。


1
投票

你可以把它包裹成一个块:

int c = ({ static_assert(true); }, 4);

0
投票

一个选项是使用语句表达式(GCC 扩展,除 MSVC 之外的所有内容都支持):

int c = ( ({ static_assert(true); }), 4);

如果在启用

-Wcomma
警告的情况下进行编译,则需要将静态断言语句表达式强制转换为
void
以解决“可能误用逗号运算符”警告消息:

int c = ( (void)({ static_assert(true); }), 4);
© www.soinside.com 2019 - 2024. All rights reserved.