I'm trying to implement my own boolean class, but cannot replicate native semantics for &&. The following contrived code demonstrates the issue:
#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;
}
When compiled and run, the result is:
Native && First Overloaded && Second First
In other words, && on bools is lazy (as any C++ programmer would expect) but the overloaded && isn't (as this C++ programmer at least didn't expect).
Is there a way to make overloaded && lazy? I can find various full-on lazy evaluation schemes to provide Haskell-like functionality, but they seem like complete overkill for my use case.
If you really want short-circuiting and are willing to sacrifice the operator syntax, you can rename your
operator&&
method to_and
, define anAND()
macro, and writeAND(x,y)
instead ofx&&y
.With some macro hacks you can have
AND()
accept a variable number of parameters.The
_and()
method here is not intended to be used "publicly" here but must be declared public since you can'tfriend
a macro.For something as simple as your
MyBool
class, this is probably unnecessary. But if you need youroperator&&
to have special side-effects like updating some state onthis
, then this gets the job done.No.
You can make almost anything evaluate lazily with the expression template idiom, including but not limited to the operators whose built-in versions short-circuit. But that's more work than you need for this one case, since then your
MyBool
class would require a lot more code.You should not overload
bool operator&&
, since you lose short circuit evaluation, as you have discovered.The correct approach would be to give your class a bool conversion operator
Note that explicit conversion operators require C++11 compliance. If you do not have this, have a look at the safe bool idiom.