我正在尝试实现自己的布尔类,但无法复制&&的本机语义。以下设计的代码演示了这个问题:
#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 << " First\n"; return false;}
bool f2() {std::cout << " Second\n"; return false;}
int main(int argc, char** argv) {
std::cout << "Native &&\n";
f1() && f2();
std::cout << "Overloaded &&\n";
MyBool(f1()) && MyBool(f2());
return 0;
}
编译并运行时,结果为:
Native && First Overloaded && Second First
换句话说,&amp;&amp;在bools上是懒惰的(正如任何C ++程序员所期望的那样)但是过载的&amp;&amp;不是(因为这个C ++程序员至少没想到)。
有没有办法让重载&amp;&amp;懒?我可以找到各种全面的延迟评估方案来提供类似Haskell的功能,但是对于我的用例来说它们似乎完全有点过分。
答案 0 :(得分:15)
你不应该重载bool operator&&
,因为你已经发现了短路评估。
正确的方法是为您的班级提供一个bool转换运算符
class MyBool {
public:
bool theValue;
MyBool() {}
MyBool(bool aBool) : theValue(aBool) {}
explicit operator bool() { return theValue; }
};
请注意,显式转换运算符需要符合C ++ 11标准。如果您没有这个,请查看safe bool idiom。
答案 1 :(得分:4)
有没有办法让重载&amp;&amp;懒惰?
没有
答案 2 :(得分:2)
您可以使用the expression template idiom进行几乎所有评估,包括但不限于内置版本短路的运算符。但是,这比你需要的工作更多,因为那时你的MyBool
类需要批次更多的代码。
答案 3 :(得分:0)
如果您真的想要短路并愿意牺牲运算符语法,可以将operator&&
方法重命名为_and
,定义AND()
宏,然后写{{1而不是AND(x,y)
。
x&&y
对于某些macro hacks,您可以#define AND(x,y) (x._and(x.theValue ? y : MyBool(false)))
接受可变数量的参数。
这里的AND()
方法不打算在这里“公开”使用,但必须公开宣布,因为你不能_and()
一个宏。
对于像friend
类这样简单的事情,这可能是不必要的。但是,如果您需要MyBool
具有特殊的副作用,例如更新operator&&
上的某个状态,那么这可以完成工作。