struct S { bool val; explicit S(bool b) : val(b) {} bool is_true () const { return val; } }; S operator && (const S & s1, const S & s2) { return s1.is_true()? S{s1.val && s2.val} : s1; } int main(void) { S s1{false}, s2{true}, s3{true}; S s4 = s1 && s2 && s3; // false }

#include <iostream> struct S { bool val; explicit S(int i) : val(i) {} explicit S(bool b) : val(b) {} template <class Expr> S (const Expr & expr) : val(evaluate(expr).val) { } template <class Expr> S & operator = (const Expr & expr) { val = evaluate(expr).val; return *this; } bool is_true () const { return val; } }; S logical_and (const S & lhs, const S & rhs) { std::cout << "&& "; return S{lhs.val && rhs.val}; } S logical_or (const S & lhs, const S & rhs) { std::cout << "|| "; return S{lhs.val || rhs.val}; } const S & evaluate(const S &s) { return s; } template <class Expr> S evaluate(const Expr & expr) { return expr.eval(); } struct LazyAnd { template <class LExpr, class RExpr> auto operator ()(const LExpr & l, const RExpr & r) const { const auto & temp = evaluate(l); return temp.is_true()? logical_and(temp, evaluate(r)) : temp; } }; struct LazyOr { template <class LExpr, class RExpr> auto operator ()(const LExpr & l, const RExpr & r) const { const auto & temp = evaluate(l); return temp.is_true()? temp : logical_or(temp, evaluate(r)); } }; template <class Op, class LExpr, class RExpr> struct Expr { Op op; const LExpr &lhs; const RExpr &rhs; Expr(const LExpr& l, const RExpr & r) : lhs(l), rhs(r) {} auto eval() const { return op(lhs, rhs); } }; template <class LExpr> auto operator && (const LExpr & lhs, const S & rhs) { return Expr<LazyAnd, LExpr, S> (lhs, rhs); } template <class LExpr, class Op, class L, class R> auto operator && (const LExpr & lhs, const Expr<Op,L,R> & rhs) { return Expr<LazyAnd, LExpr, Expr<Op,L,R>> (lhs, rhs); } template <class LExpr> auto operator || (const LExpr & lhs, const S & rhs) { return Expr<LazyOr, LExpr, S> (lhs, rhs); } template <class LExpr, class Op, class L, class R> auto operator || (const LExpr & lhs, const Expr<Op,L,R> & rhs) { return Expr<LazyOr, LExpr, Expr<Op,L,R>> (lhs, rhs); } std::ostream & operator << (std::ostream & o, const S & s) { o << s.val; return o; } S and_result(S s1, S s2, S s3) { return s1 && s2 && s3; } S or_result(S s1, S s2, S s3) { return s1 || s2 || s3; } int main(void) { for(int i=0; i<= 1; ++i) for(int j=0; j<= 1; ++j) for(int k=0; k<= 1; ++k) std::cout << i << j << k << " " << and_result(S{i}, S{j}, S{k}) << std::endl; for(int i=0; i<= 1; ++i) for(int j=0; j<= 1; ++j) for(int k=0; k<= 1; ++k) std::cout << i << j << k << " " << or_result(S{i}, S{j}, S{k}) << std::endl; return 0; }

000 0 001 0 010 0 011 0 100 && 0 101 && 0 110 && && 0 111 && && 1 000 || || 0 001 || || 1 010 || 1 011 || 1 100 1 101 1 110 1 111 1