【发布时间】:2022-11-29 00:50:10
【问题描述】:
我一直在寻找更多适用于 std::exchange 的习语。
今天我发现自己writing this 在一个答案中:
do {
path.push_front(v);
} while (v != std::exchange(v, pmap[v]));
我比说更喜欢它
do {
path.push_front(v);
if (v == pmap[v])
break;
v= pmap[v];
} while (true);
希望出于显而易见的原因。
但是,我不太喜欢标准语,我不禁担心 lhs != rhs 不能保证右侧表达式在左侧表达式之前没有被完全计算。这将使它成为一个同义反复的比较——根据定义它会返回 true。
然而,代码确实运行正确,显然首先评估了 lhs。
有人知道吗
- 标准是否保证这个评价顺序
- 如果它在最近的标准中发生了变化,哪个标准版本首先规定了它?
附言。我意识到这是 f(a,b) 的特例,其中 f 是 operator!=。我试图使用此处找到的信息回答我自己的查询,但迄今为止未能得出结论:
【问题讨论】:
-
嗯...如果
operator !=是成员timsong-cpp.github.io/cppwp/n4868/expr.call#8,则可能格式正确 - 它肯定不会比标准自己的示例复杂 -
我没有看到任何要求
!=的左侧在右侧之前排序的措辞。 C++17 为某些操作添加了顺序,但!=似乎不在其中。 -
@rturrado 我喜欢认为“原子”(如单语句)交换的循环更清晰。但是,是的,没有它似乎更安全。哪个恕我直言是不明显的部分。我让危险传感器关闭的唯一原因是因为我在过去吸取了痛苦的 C++ 教训。但我希望普通程序员对代码应该做什么有相同的、完全直观的期望。
-
@rturrado 是的,双
pmap[v]可以通过添加命名变量来规避。 las,没有办法限制所述变量的范围。重写为 for 循环(通常)需要使推送操作成为条件的副作用(这在客观上更糟,因为与std::exchange不同,该操作还不存在具有众所周知的语义)或者...在循环体之外复制它...这是第 22 条军规 -
FWIW。
标签: c++ language-lawyer sequence-points