C++ 对表达式求值,直到返回true

C++ 对表达式求值,直到返回true,c++,idioms,C++,Idioms,我有一个savePotentialState(…)-函数,如果要保存更改,则返回true,如果未执行任何操作,则返回false。此外,我知道在通过主回路的任何一次过程中,最多可能有一个电位计发生了变化(由于它们的读取方式) 这是在一个时间非常有限的嵌入式平台上,所以我不必频繁调用savestate,这一点很重要(至少很重要)。然而,我提出的代码自然看起来很愚蠢,很可能最终会出现在DailyWF: if (!savePotentiometerState(pot1)) if (!savePote

我有一个
savePotentialState(…)
-函数,如果要保存更改,则返回
true
,如果未执行任何操作,则返回
false
。此外,我知道在通过主回路的任何一次过程中,最多可能有一个电位计发生了变化(由于它们的读取方式)

这是在一个时间非常有限的嵌入式平台上,所以我不必频繁调用
savestate
,这一点很重要(至少很重要)。然而,我提出的代码自然看起来很愚蠢,很可能最终会出现在DailyWF:

if (!savePotentiometerState(pot1))
  if (!savePotentiometerState(pot2))
    ...
      if (!savePotentiometerState(potn));
另一种方法是使用短路评估:

const bool retval = savePotentiometerState(pot1) || savePotentiometerState(pot2) || ... || savePotentiometerState(potn);
我想我甚至可以把作业放在这里。但这感觉也不太好,因为我滥用了
|
操作符的短路

各种
potn
对象都是包含类的成员变量,因此没有明显的方法将其编写为循环


我觉得我在这里遗漏了一些明显的东西,所以我的问题是:有没有一种惯用的/易于阅读的方法可以做到这一点,而不会牺牲效率?如果重要的话,我使用的是C++17。

循环似乎是一种方法:

for (auto& pot : {std::ref(pot1), std::ref(pot2), /*..,*/ std::ref(potn)}) {
     if (savePotentiometerState(pot)) {
         break;
     }
}

就我个人而言,我会避免你使用的算法

我会一直为每一个罐子保存国家;并跟踪当前和以前的值;然后仅在值发生更改时调用给定的回调


通过这种方式,
savePotState
总是与给定pot的速度一样快;而且您永远不会进入pot1到pot(n-1)可以阻止读取potn的状态。

因为您可以使用C++17,所以您可以利用并编写一个帮助函数来为您执行评估

template<typename... Args>
bool returtnPotentiometerState(Args&&... args)
{
    return (... || savePotentiometerState(args));
}

这意味着你没有回路,你会短路。

为什么你认为这会是短路操作符的“缺席”?这正是它的好处…与其拥有不同的变量,为什么不拥有一个数组或一个元素向量呢?然后很容易从开始到结束循环,一旦函数返回true,就可以中断循环。顺便说一句,由于不需要更改现有代码来反映新的或删除的变量,因此添加或删除对象也更容易。当然,也可以减少类中成员的数量。@user463035818我想是因为我把
|
看作是一种逻辑操作,我在这里直接使用它来控制程序流。。。但你可能是对的,也许这是最好的方法。请提供一个答案。你的问题充满了奇怪的前提,这使得你很难理解你真正的问题是什么。每个人都在尝试矢量化,你们想回到循环吗?+1,这正是我想要的替代方案!不过,我需要检查这个循环是如何编译的:如果编译器确实在堆栈上创建引用数组(作为指针),这可能比每次为所有pot调用
savestate
要慢,而且还需要占用堆栈空间(系统总共有96K RAM,所以这里的内存量很小)。非常好…可读性好,测试简单。饥饿(由硬件使用不当引起)可能很难诊断,甚至难以识别。(去过那里,做到了)我想就是这样:它不应该比手工编写条件慢,我可以命名helper函数来准确地表示代码的意图。@Timo这很可能会慢一些。因为它需要引用,所以它必须取消引用以获得它的值,因为编译器不知道是否有其他东西进行了修改。哟ur
const bool retval=
或if语句可能是最快的。Jarods也可能具有相同的速度,因为引用是作用域的本地引用,所以编译器知道它们不会更改。您可以使用来测试。嗯,我可以想象,由于引用是本地引用,并且假设帮助程序内联,它应该是非常简单的编译器很容易消除引用…但是当然,假设是所有******的母亲,所以也许明天我会编写快速测试台测试(顺便说一下,感谢链接!)@Timo没问题。如果它是内联的,那就不成问题了。我只是想指出它可能会慢一些。@Hiroki感谢您编写了这个测试!事实上,循环似乎比原始的
|
ing还要快,很有趣!另一方面,将编译器更改为GCC7.2会使原始的方式变得最快,折叠表达式非常复杂其次,在我的例子中,编译器实际上是gcc arm ONE eabi 7.2,因此我需要使用它来尝试基准测试,因为结果非常接近。
if (returtnPotentiometerState(pot1, pot2, ..., potn))