懒惰、重载的 C++ && 运算符?

问题描述 投票:0回答:4

我正在尝试实现我自己的布尔类,但无法复制 && 的本机语义。以下人为的代码演示了该问题:

#include <iostream>

class MyBool {
public:
    bool theValue;
    MyBool() {}
    MyBool(bool aBool) {theValue = aBool;}
    MyBool operator&& (MyBool aBool) {return theValue && aBool.theValue;}
};

bool f1() {std::cout &lt;&lt; "   First\n"; return false;}
bool f2() {std::cout &lt;&lt; "   Second\n"; return false;}

int main(int argc, char** argv) {
    std::cout &lt;&lt; "Native &&\n";
    f1() && f2();
    std::cout &lt;&lt; "Overloaded &&\n";
    MyBool(f1()) && MyBool(f2());
    return 0;
}

编译运行后结果为:

Native &&
   First
Overloaded &&
   Second
   First

换句话说,bool 上的 && 是惰性的(正如任何 C++ 程序员所期望的那样),但重载的 && 却不是(正如这个 C++ 程序员至少没有期望的那样)。

有没有办法让重载&&变得懒惰?我可以找到各种全面的惰性评估方案来提供类似 Haskell 的功能,但它们对于我的用例来说似乎完全是多余的。

c++ boolean operator-keyword lazy-evaluation
4个回答
17
投票

您不应该过载

bool operator&&
,因为正如您所发现的,您会失去短路评估。

正确的方法是为你的类提供一个 bool 转换运算符

class MyBool {
 public:
  bool theValue;
  MyBool() {}
  MyBool(bool aBool) : theValue(aBool) {}
  explicit operator bool() { return theValue; }
};

请注意,显式转换运算符需要符合 C++11。如果您没有这个,请查看safe bool idiom


6
投票

有没有办法让重载&&变得懒惰?

没有。


2
投票

您可以使用表达式模板惯用语使几乎任何东西进行延迟计算,包括但不限于内置版本短路的运算符。但这比您在这种情况下需要的工作量要多,因为那时您的

MyBool
类将需要很多更多代码。


0
投票

如果您确实想要短路并且愿意牺牲运算符语法,您可以将

operator&&
方法重命名为
_and
,定义
AND()
宏,并编写
AND(x,y)
而不是
x&&y

#define AND(x,y) (x._and(x.theValue ? y : MyBool(false)))

通过一些宏黑客,您可以让

AND()
接受可变数量的参数。

此处的

_and()
方法不打算在此处“公开”使用,但必须声明为公开,因为您不能
friend
宏。

对于像您的

MyBool
类这样简单的事情,这可能是不必要的。但是,如果您需要
operator&&
具有特殊的副作用,例如更新
this
上的某些状态,那么这就可以完成工作。

© www.soinside.com 2019 - 2024. All rights reserved.