I'm writing a variadic templated function that should implement a "domino" update. That is to say: given a predicate p
, it should iterate over multiple lval
s (passed by reference) and assign val
to them, until p(val, lval)
returns false
at which point the process stops.
This is my current implementation:
#include <iostream>
#include <functional>
template<class Val, class P>
void domino_update(P, Val&) {}
template<class Val, class Lval, class... More, class P>
void domino_update(P p, Val&& val, Lval& lval, More&... more)
{
if (p(val, lval)) {
lval = val; // No need to forward since it'd potentially chain more copies anyway
domino_update(p, val, more...);
}
}
int main(int, char**)
{
int i = 8, j = 9, k = 1;
domino_update(std::less{}, 2, i, j, k);
std::cout << i << ' ' << j << ' ' << k << '\n'; // Prints 2 2 1
return 0;
}
However, I don't like the fact that it's recursive.
Can I use a fold expression to avoid using recursion (and avoid the need to implement a base case for the template), while maintaining the short-circuiting logic (i.e., p
should not be called again once it has returned false
)? How?
Here's one way:
template <class P, class Val, class... Lvals>
void domino_update(P p, Val&& val, Lvals&&... lval) {
((/*if*/ p(val, lval)
/*then*/ && (lval = val, true))
/*and next*/ && ...);
}