我收到GCC 10.1关于可能的未定义行为的警告。叮当10没有警告。
warning: operation on 'init' may be undefined [-Wsequence-point]
| (x = ... = (init = fold_op(init, elements), 0));
| ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
以下是导致警告的代码段:
template <typename T, typename BinaryOp, typename... Pack>
constexpr auto reverse_reduce(T init, BinaryOp&& fold_op, Pack&&... elements) -> T
{
auto x = 0;
(x = ... = (init = fold_op(init, elements), 0));
return init;
}
它使用operator=
和折叠表达式技巧对参数包执行反向"迭代"。
海湾合作委员会在这里警告是正确的吗?还是定义明确的行为?
这是我在重现错误时所能做到的最小
:auto x = 0;
auto i = 0;
((x = (i = i, 0)) = (i = i, 0))
我读到的关于序列点、计算顺序和运算符优先级/关联性的所有内容都让我认为这是很好的定义,但规则太多了,我不是专家。
让我相信警告是正确的一件事是,当我将结果分配给 clang 中的constexpr
变量时,结果与非constexpr
评估中的结果不同。
您可以使用 lambda 来消除警告。
例:
template <typename T, typename BinaryOp, typename... Pack>
constexpr auto reverse_reduce(T init, BinaryOp&& fold_op, Pack&&... elements) -> T {
auto x = 0;
auto inner = [&](const auto& v) {init = fold_op(init, v); };
(x = ... = (inner(elements), 0));
return init;
}