Ran*_*nza -1 c++ gcc clang fold-expression
最近我想出了一个想法,如何枚举参数包(脉冲)中的元素,我对这个解决方案很满意一段时间:
lastValue = 0.0; i = -1;
lastValue += (... + ((time <= endtimes[++i] && time >= delays[i]) ? static_cast<Pulses*>(fields[i])->operator()(time - delays[i]) : 0.0));
Run Code Online (Sandbox Code Playgroud)
但是现在当我尝试使用 Clang 而不是 GCC 进行编译时,我收到了以下警告
警告:对“i”的多次未排序修改 [-Wunsequenced]
我读过几篇关于无序修改的帖子,但在他们的例子中,修改要么在表达式中发生两次,要么发生在“=”运算符的左侧。
另一方面,我的理解是参数包是按顺序评估的,所以......没有未排序的行为,对吗?或者我在这里完全错了,编译器总是对的?
Clang 是对的,代码导致 UB。
折叠表达式的计算规则与普通表达式完全相同。
的两个操作数的评价+(以及大多数二元运算)是未测序相对于彼此(即可以以任何顺序发生,可能是交错的),并导致UB标量变量的未测序的改变。
解决方案很简单:使用运算符,进行折叠,而不是+. 对于,,第一个操作数在第二个操作数之前完全评估,因此有一个明确的评估顺序并且没有 UB。
lastValue = 0.0; i = -1;
((lastValue += ((time <= endtimes[++i] && time >= delays[i]) ? static_cast<Pulses*>(fields[i])->operator()(time - delays[i]) : 0.0)), ...);
Run Code Online (Sandbox Code Playgroud)
或者,使用 lambda 使其不那么难看:
lastValue = 0.0; i = 0;
([&]{
if (time <= endtimes[i] && time >= delays[i])
lastValue += static_cast<Pulses*>(fields[i])->operator()(time - delays[i]);
i++;
}(), ...);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
55 次 |
| 最近记录: |