【问题标题】:Short-circuit evaluation on C++ logical && and || operatorsC++ 逻辑 && 和 || 的短路评估运营商
【发布时间】:2016-06-25 10:19:16
【问题描述】:

C++ 中的用户重载逻辑运算符 (&&, ||) 的行为类似于常规函数。也就是说,bool operator&&(const T &a, const T2 &b); 中的两个参数都在进入函数之前进行评估,因为进入函数是 C++ 中的序列点 [1]。到这里为止一切顺利。

现在,“内置运算符 && 和 ||进行短路评估”[2][3],其中左右两侧之间有一个序列点。引用的参考文献不清楚“内置”是什么,只是它们采用bool 操作数,或使用“上下文转换为布尔值”将它们转换。它还提到只有“两个标准库类重载了这些运算符 [因为] 短路属性 (...) 不适用于重载,而且具有布尔语义的类型并不常见。” [2]

具有布尔语义的类型? “内置运算符”究竟是如何工作的?用短路评估来定义逻辑运算符是不可能的吗?

[1]https://en.wikipedia.org/wiki/Sequence_point

[2]http://en.cppreference.com/w/cpp/language/operator_logical

[3]https://en.wikipedia.org/wiki/Short-circuit_evaluation

【问题讨论】:

  • "用短路求值来定义逻辑运算符是不可能的吗?"是的,这“根本不可能”。您的运算符函数需要两个参数,完全评估,这意味着编译器根本不能做任何短路。如果您想要对您的自定义类型进行短路评估,则需要将转换运算符实现为 bool 而不是逻辑运算符。
  • 我的阅读是“内置”是指“这是一种内置的语言功能”,而不是“这是标准库的一部分”。你不能制作自己的内置运算符,除非你用自己的非标准扩展制作自己的编译器。
  • @JoachimPileborg 我认为短路可以在用户定义的逻辑操作中实现,虽然这不会是微不足道的

标签: c++ c++11 operators short-circuiting


【解决方案1】:

您可以想象短路&& 的行为如下:

bool b = expr1 && expr2;

首先,它需要 expr1expr2 并将它们存储在 lambdas 中:

bool b = and_helper( [&]{return expr1;}, [&]{return expr2;} );

并将它们转发给一个助手,其中and_helper 是(略微简化):

template<class Lhs, class Rhs>
bool and_helper( Lhs&& lhs, Rhs&& rhs ) {
  if (lhs()) return rhs();
  return false;
}

这具有类似的短路行为。

为了让用户覆盖的 &amp;&amp; 以这种方式工作,我们必须自动 lambda 参数并将所述 lambda 传递给用户编写的 operator&amp;&amp;

因此,用户定义操作发生这种情况的唯一障碍是语法。您可以在对类型进行相对机械的转换后获得相同的行为,而无需求助于魔法。

编译器在遇到该结构时只是做了一个大致等效的操作(甚至在 lambda 存在之前)。

【讨论】:

    【解决方案2】:

    这意味着短路不适用于用户定义的运算符。

    这是因为,正如您所说,它们的行为类似于函数。

    【讨论】:

      猜你喜欢
      • 2013-06-02
      • 2013-08-23
      • 2012-02-10
      • 2021-12-16
      • 2012-01-18
      • 1970-01-01
      • 2021-11-21
      • 2013-08-25
      相关资源
      最近更新 更多