Commentators explained that the reason why nWrap
can't produce an optimized return value here is because it would change the return type of the (non-templated) function.
With that, I found that embedding nCalls
return value into another lambda definition (and thus a distinct type), will enable compilers to eliminate the loop:
static inline constexpr auto nWrap(std::size_t n) {
return [n]() { for (std::size_t i = 0; i != n; ++i) call(); };
};
std::function<void()> nCalls(std::size_t n) {
if (n == 1) {
return []{nWrap(1)();}; // Return value embedded into another lambda
}
return nWrap(n);
}
std::function<void()> oneCall() { return nCalls(1); }
Results in oneCall
always returning an optimized std::function
and nCalls
deciding at runtime what to return – which isn't what I asked for, but it's what I'm currently settling with.