I have some predicate objects that take some value and return the result of some criteria. (My real implementation is more complex, this is only a minimal example):
struct PredEven
{
bool passes(int x) const { return x%2 == 0; }
};
struct PredGreaterThan
{
int limit;
bool passes(int x) const { return x > limit; }
};
using Predicate = std::variant<PredEven, PredGreaterThan>;
I store objects of these types in a std::array
and now want to test some value against all of these.
The straight-forward implementation would be this:
const std::array<Predicate, 2> predicates = {PredEven{}, PredGreaterThan{3}};
const int valToTest = 4;
bool allPassed1 = true;
for(const auto& var : predicates)
{
allPassed1 &= std::visit([&valToTest](const auto& p){ return p.passes(valToTest); }, var);
}
However, I really should be using std::all_of for this. Better yet, the ranges version:
const bool allPassed2 = std::ranges::all_of(predicates, [&valToTest](const auto& var)
{ return std::visit([&valToTest](const auto& p){ return p.passes(valToTest); }, var); });
This code is concise but rather hard to read (and to format). Particularly the nested lambda isn't great. It does have the advantage that the result can be const
.
Is there any way to get rid of the nested lambda or make this more readable?
1 Answer 1
The easiest thing to do is to hide away the complexity in a function or class. One possibility is to create a function that returns the nested lambda, like so:
static auto passes(auto valToTest) {
return [valToTest](const auto& var) {
return std::visit([&valToTest](const auto& p) {
return p.passes(valToTest);
}, var);
};
}
const bool allPassed3 = std::ranges::all_of(predicates, passes(valToTest));
There are other ways to reduce the amount of lambdas perhaps, like using std::bind
and/or creating a class that has an operator()
, but in the end that will probably be equally or even more hard to read as lambdas are basically shorthand for that.
-
\$\begingroup\$ That's what I feared. The idea of giving the lambdas a concise name is good, I settled on a local variable instead of a function. \$\endgroup\$perivesta– perivesta2022年05月11日 10:36:21 +00:00Commented May 11, 2022 at 10:36