title: Combining predicates in a functional way and allowing short-circuiting to work
body: <h2>Foreword</h2>
  <p>I asked <a href="https://stackoverflow.com/questions/64259413/combining-predicates-in-a-functional-way">a similar</a> question: say I have a predicate <code>auto p1 = [](int x){ return x &gt; 2; }</code> and a predicate <code>auto p2 = [](int x){ return x &lt; 6; }</code>, how do I combine <code>p1</code> and <code>p2</code> to obtain <code>p1and2</code> such that <code>p1and2(x) == p1(x) &amp;&amp; p2(x)</code>? The answer was <em>use <a href="https://www.boost.org/doc/libs/1_71_0/libs/hana/doc/html/group__group-functional.html#ga3a8316acd5efa22c3d1861b62d5df3c2" rel="nofollow noreferrer"><code>boost::hana::demux</code></a></em> (refer to the linked question for details).</p>
  <h2>The new problem and the question</h2>
  <p>Sometimes, however, the evaluation of one predicate should occur only if the other predicate evaluates to a given truthness value, e.g. <code>true</code>.</p>
  <p>For instance one predicate might be</p>
  <pre class="lang-cpp prettyprint-override"><code>constexpr auto has_value = [](std::optional&lt;int&gt; opt){ return opt.has_value(); };
  </code></pre>
  <p>and the other predicate</p>
  <pre class="lang-cpp prettyprint-override"><code>constexpr auto has_positive = [](std::optional&lt;int&gt; opt){ return opt.value() == 3; };
  </code></pre>
  <p>It's easy to recognize the following</p>
  <pre class="lang-cpp prettyprint-override"><code>bool b1 = has_value(some_opt_int) &amp;&amp; has_positive(some_opt_int); // true or false, but just fine either way
  bool b2 = has_positive(some_opt_int) &amp;&amp; has_value(some_opt_int); // runtime error if !some_opt_int.has_value()
  </code></pre>
  <p>Defining</p>
  <pre class="lang-cpp prettyprint-override"><code>constexpr auto all = boost::hana::demux([](auto const&amp;... x) { return (x &amp;&amp; ...); });
  </code></pre>
  <p>and using it like so</p>
  <pre class="lang-cpp prettyprint-override"><code>std::optional&lt;int&gt; empty{};
  contexpr auto has_value_which_is_positive = all(has_value, has_positive);
  bool result = has_value_which_is_positive(empty);
  </code></pre>
  <p>would lead to failure at run time, because <a href="https://stackoverflow.com/a/43048635/5825294">the it's the function call to the variadic generic lambda wrapped in <code>all</code> which forces the evaluation of its arguments, not the fold expression <code>(x &amp;&amp; ...)</code></a>.</p>
  <p>So my question is, how do I combine <code>has_value</code> and <code>has_positive</code> to get <code>has_value_which_is_positive</code>? More in general, how do I &quot;and&quot; together several predicates such that they're evaluated only as much as the short-circuit mechanism requires?</p>
  <h2>My attempt</h2>
  <p>I think that, in order to prevent the predicates from being evaluated, I can have wrap them in some function objects which, when applied to the argument (the <code>std::optional</code>), give back another object which wraps the predicate and the <code>std::optional</code> together, and has an <code>operator bool</code> conversion function which would be triggered only when the fold expression is evaluated.</p>
  <p>This is my attempt, which is miserably undefined behavior because the assertion in <code>main</code> sometimes fails and sometimes doesn't:</p>
  <pre><code>#include &lt;optional&gt;
  
  #include &lt;boost/hana/functional/demux.hpp&gt;
  #include &lt;boost/hana/functional/curry.hpp&gt;
  
  template&lt;typename P, typename T&gt;
  struct LazilyAppliedPred {
      LazilyAppliedPred(P const&amp; p, T const&amp; t)
          : p(p)
          , t(t)
      {}
      P const&amp; p;
      T const&amp; t;
      operator bool() const {
          return p(t);
      }
  };
  
  constexpr auto lazily_applied_pred = [](auto const&amp; p, auto const&amp; t) {
      return LazilyAppliedPred(p,t);
  };
  
  auto constexpr lazily_applied_pred_curried = boost::hana::curry&lt;2&gt;(lazily_applied_pred);
  
  constexpr auto all_true = [](auto const&amp;... x) { return (x &amp;&amp; ...); };
  
  constexpr auto all = boost::hana::demux(all_true);
  
  constexpr auto has_value = [](std::optional&lt;int&gt; o){
      return o.has_value();
  };
  constexpr auto has_positive = [](std::optional&lt;int&gt; o){
      assert(o.has_value());
      return o.value() &gt; 0;
  };
  
  int main() {
      assert(all(lazily_applied_pred_curried(has_value),
                 lazily_applied_pred_curried(has_positive))(std::optional&lt;int&gt;{2}));
  }
  </code></pre>
  <p>(<a href="https://stackoverflow.com/questions/66127093/short-circuiting-in-fold-expressions">Follow up question</a>.)</p>