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.