Я пытаюсь реализовать свой собственный логический класс, но не могу воспроизвести собственную семантику для &&, Следующий придуманный код демонстрирует проблему:
#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, но они кажутся излишними для моего варианта использования.
Вы не должны перегружать bool operator&&
, так как вы потеряете оценку короткого замыкания, как вы обнаружили.
Правильный подход — дать вашему классу оператор преобразования bool
class MyBool {
public:
bool theValue;
MyBool() {}
MyBool(bool aBool) : theValue(aBool) {}
explicit operator bool() { return theValue; }
};
Обратите внимание, что для явных операторов преобразования требуется соответствие C ++ 11. Если у вас нет этого, взгляните на безопасная идиома.
Есть ли способ сделать перегруженным && ленивый?
Нет.
Вы можете сделать почти все, что лениво оценить идиома шаблона выражения, включая, но не ограничиваясь, операторов, чьи встроенные версии короткого замыкания. Но это больше работы, чем нужно для этого случая, с тех пор ваш MyBool
класс потребует много больше кода
Если вы действительно хотите короткого замыкания и готовы пожертвовать синтаксисом оператора, вы можете переименовать свой 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
, тогда это делает работу.