8

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



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

编译运行后,结果为:

    本国的 &&
       第一的
    重载 &&
       第二
       第一的

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

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

4

4 回答 4

15

正如你所发现的,你不应该超载bool operator&&,因为你失去了短路评估。

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

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

请注意,显式转换运算符需要符合 C++11。如果你没有这个,看看安全布尔成语

于 2013-04-16T08:10:04.050 回答
5

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

不。

于 2013-04-16T08:10:45.357 回答
2

您可以使用表达式模板 idiom使几乎任何东西都懒惰地计算,包括但不限于内置版本短路的运算符。但这比您在这种情况下所需的工作要多,因为那时您的MyBool课程将需要更多的代码。

于 2013-04-16T09:29:40.187 回答
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,那么这就完成了工作。

于 2016-01-01T15:21:11.173 回答