2016-03-10 66 views
0

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

现在,“内建运营商& &和||执行短路评估“[2] [3],其中左侧和右侧之间存在序列点。引用的参考文献不清楚“内建”是什么,只是它们采用bool操作数,或者使用“上下文转换为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

+4

“定义符合短路评估的逻辑运算符是不可能的?”是的,这是“根本不可能的”。您的运算符函数需要两个参数,完全评估,这意味着编译器不能做任何短路。如果你想对你的自定义类型进行短路评估,那么你需要将转换运算符实现为'bool'而不是逻辑运算符。 –

+1

我的阅读是“内建”是指“这是一种内置的语言功能”,而不是“这是标准库的一部分”。你不能创建你自己的内建操作符,除非你用自己的非标准扩展名创建自己的编译器。 –

+0

[实际上是否有重载&&和||的原因不要短路?(http://stackoverflow.com/questions/25913237/is-there-actually-a-reason-why-overloaded-and-dont-short-circuit) – quamrana

回答

0

这意味着短路并不适用于用户定义的操作符。

这是因为,正如你所说,他们的行为像功能。

2

你可以想像,短路&&行为是这样的:

bool b = expr1 && expr2; 

第一,它需要在lambda表达式expr1expr2,并将它们存储:

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; 
} 

这有类似的短路行为。

对于用户覆盖的&&以这种方式工作,我们必须自动对参数进行lambda表达并将所述lambda表达式传递给用户编写的operator&&

因此,用户定义操作发生这种情况的唯一障碍是语法。在对类型进行相对机械的转换之后,你可以得到相同的行为,而不诉诸魔法。

编译器在运行到该构造时只做了大致等效的操作(即使在lambda存在之前)。