在折叠表达式中使用后增量是否会产生未排序的行为?
Does using postincrement within a fold-expression give unsequenced behaviour?
最近我想到了如何枚举参数包 (Pulses) 中的元素的想法,我对这个解决方案很满意一段时间:
lastValue = 0.0; i = -1;
lastValue += (... + ((time <= endtimes[++i] && time >= delays[i]) ? static_cast<Pulses*>(fields[i])->operator()(time - delays[i]) : 0.0));
然而,当我尝试使用 Clang 而不是 GCC 进行编译时,我收到了以下警告
warning: multiple unsequenced modifications to 'i' [-Wunsequenced]
我读过一些关于无序修改的帖子,但在他们的示例中,修改要么在表达式中发生两次,要么发生在“=”运算符的左侧。
另一方面,我的理解是参数包是按顺序计算的,所以...没有未排序的行为吧?或者我在这里完全错了,编译器总是正确的?
好吧,编译器永远是对的,即使它错了……
除非你删除的...中使用了 i,否则我看不出有什么问题。另一方面,表达式过于复杂,可以拆分,甚至只是为了使调试更容易。
Clang 是对的,代码导致 UB。
折叠表达式的计算规则与普通表达式完全相同。
+
(以及大多数二元运算符)的两个操作数的计算是 unsequenced 相对于彼此(即可以以任何顺序发生,可能交错),以及标量的无序变化变量导致 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)), ...);
或者,使用 lambda 让它不那么难看:
lastValue = 0.0; i = 0;
([&]{
if (time <= endtimes[i] && time >= delays[i])
lastValue += static_cast<Pulses*>(fields[i])->operator()(time - delays[i]);
i++;
}(), ...);
最近我想到了如何枚举参数包 (Pulses) 中的元素的想法,我对这个解决方案很满意一段时间:
lastValue = 0.0; i = -1;
lastValue += (... + ((time <= endtimes[++i] && time >= delays[i]) ? static_cast<Pulses*>(fields[i])->operator()(time - delays[i]) : 0.0));
然而,当我尝试使用 Clang 而不是 GCC 进行编译时,我收到了以下警告
warning: multiple unsequenced modifications to 'i' [-Wunsequenced]
我读过一些关于无序修改的帖子,但在他们的示例中,修改要么在表达式中发生两次,要么发生在“=”运算符的左侧。
另一方面,我的理解是参数包是按顺序计算的,所以...没有未排序的行为吧?或者我在这里完全错了,编译器总是正确的?
好吧,编译器永远是对的,即使它错了……
除非你删除的...中使用了 i,否则我看不出有什么问题。另一方面,表达式过于复杂,可以拆分,甚至只是为了使调试更容易。
Clang 是对的,代码导致 UB。
折叠表达式的计算规则与普通表达式完全相同。
+
(以及大多数二元运算符)的两个操作数的计算是 unsequenced 相对于彼此(即可以以任何顺序发生,可能交错),以及标量的无序变化变量导致 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)), ...);
或者,使用 lambda 让它不那么难看:
lastValue = 0.0; i = 0;
([&]{
if (time <= endtimes[i] && time >= delays[i])
lastValue += static_cast<Pulses*>(fields[i])->operator()(time - delays[i]);
i++;
}(), ...);