boolean — Ленивый, перегруженный C ++ & amp; оператор?

Я пытаюсь реализовать свой собственный логический класс, но не могу воспроизвести собственную семантику для &&, Следующий придуманный код демонстрирует проблему:



#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, но они кажутся излишними для моего варианта использования.

8

Решение

Вы не должны перегружать bool operator&&, так как вы потеряете оценку короткого замыкания, как вы обнаружили.

Правильный подход — дать вашему классу оператор преобразования bool

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

Обратите внимание, что для явных операторов преобразования требуется соответствие C ++ 11. Если у вас нет этого, взгляните на безопасная идиома.

15

Другие решения

Есть ли способ сделать перегруженным && ленивый?

Нет.

4

Вы можете сделать почти все, что лениво оценить идиома шаблона выражения, включая, но не ограничиваясь, операторов, чьи встроенные версии короткого замыкания. Но это больше работы, чем нужно для этого случая, с тех пор ваш MyBool класс потребует много больше кода

2

Если вы действительно хотите короткого замыкания и готовы пожертвовать синтаксисом оператора, вы можете переименовать свой 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, тогда это делает работу.

0
По вопросам рекламы [email protected]