I'm going to play.
You want to do a curried fold over addition. We could solve this one problem, or we could solve a class of problems that include this.
So, first, addition:
auto add = [](auto lhs, auto rhs){ return std::move(lhs)+std::move(rhs); };
That expresses the concept of addition pretty well.
Now, folding:
template<class F, class T>
struct folder_t {
F f;
T t;
folder_t( F fin, T tin ):
f(std::move(fin)),
t(std::move(tin))
{}
template<class Lhs, class Rhs>
folder_t( F fin, Lhs&&lhs, Rhs&&rhs):
f(std::move(fin)),
t(
f(std::forward<Lhs>(lhs), std::forward<Rhs>(rhs))
)
{}
template<class U>
folder_t<F, std::result_of_t<F&(T, U)>> operator()( U&& u )&&{
return {std::move(f), std::move(t), std::forward<U>(u)};
}
template<class U>
folder_t<F, std::result_of_t<F&(T const&, U)>> operator()( U&& u )const&{
return {f, t, std::forward<U>(u)};
}
operator T()&&{
return std::move(t);
}
operator T() const&{
return t;
}
};
It takes a seed value and a T, then permits chaining.
template<class F, class T>
folder_t<F, T> folder( F fin, T tin ) {
return {std::move(fin), std::move(tin)};
}
Now we connect them.
auto adder = folder(add, 0);
std::cout << adder(2)(3)(4) << "\n";
We can also use folder for other operations:
auto append = [](auto vec, auto element){
vec.push_back(std::move(element));
return vec;
};
Use:
auto appender = folder(append, std::vector<int>{});
for (int x : appender(1)(2)(3).get())
std::cout << x << "\n";
Live example.
We have to call .get() here because for(:) loops doesn't understand our folder's operator T(). We can fix that with a bit of work, but .get() is easier.
f(a)(b)(c). You should be able to get it working fairly easily if you want to usef(a)(b)(c)().autofor the return type of your function, and avoid the type erasure cost ofstd::function.