fold expressions using a function recursively I have written an accumulate function similar to std::accumulate that works on a std::array. The goal is to remove the loop using fold expressions.
This code currently works in c++17:
#include &lt;array&gt;

template&lt;class U, class F&gt;
class array_accumulate_helper
{
public:
    array_accumulate_helper(U&amp; u, F f)
        : r(u), f(f)
    {
    }

    array_accumulate_helper&amp; operator&lt;&lt;(const U&amp; u)
    {
        r = f(r, u);
        return *this;
    }

private:
    F f;
    U&amp; r;
};

template&lt;class U, std::size_t N, class F, std::size_t... Is&gt;
constexpr U array_accumulate_impl(const std::array&lt;U, N&gt;&amp; u, U r, F f, std::index_sequence&lt;Is...&gt;)
{
    array_accumulate_helper h(r, f);
    (h &lt;&lt; ... &lt;&lt; u[Is]);
    return r;
}

template&lt;class U, std::size_t N, class F&gt;
constexpr U accumulate(const std::array&lt;U, N&gt;&amp; u, U r, F f)
{
    return array_accumulate_impl(u, r, f, std::make_index_sequence&lt;N&gt;());
}

template&lt;class U, std::size_t N&gt;
constexpr U accumulate(const std::array&lt;U, N&gt;&amp; u)
{
    return accumulate(u, {}, [](const U&amp; a, const U&amp; b) { return a + b; });
}

Is it possible to rewrite array_accumulate_impl using a fold expression that doesn't use array_accumulate_helper?
I can use a fold expression with an operator.
ie. using &lt;&lt; in array_accumulate_impl above.
I have been unable to write one using a function recursively.
ie. for a std::array&lt;int, 3&gt; it should expand to:
f(f(f(r, a[0]), a[1]), a[2]);
Unfortunately c++ fold expression supports only binary operators: &quot;any of the following 32 binary operators: + - * / % ^ &amp; | = &lt; &gt; &lt;&lt; &gt;&gt; += -= = /= %= ^= &amp;= |= &lt;&lt;= &gt;&gt;= == != &lt;= &gt;= &amp;&amp; || , . -&gt;*.&quot; So you can't call your custom function in pack expansion without using a wrapper.
But if your function accepts a variadic number of arguments you can use std::apply
static constexpr std::array arr{ 1, 2, 3, 4, 5, 6, 7};

static constexpr auto sum = [](auto&amp;&amp;... items) {
  return (... + items);
};

static constexpr auto accumulate = [](auto&amp;&amp; fn, const auto&amp; u) {
  return std::apply([fn = std::forward&lt;decltype(fn)&gt;(fn)](auto... item) { return fn(item...); }, u);
};

constexpr auto result = accumulate(sum, arr);

Example here.
Otherwise, you can take advantage of the comma operator:
static constexpr std::array arr{ 1, 2, 3, 4, 5, 6, 7};

static constexpr auto accumulate_impl = [](const auto&amp; a, auto init, auto&amp;&amp; fn) {
  return std::apply([fn = std::forward&lt;decltype(fn)&gt;(fn), &amp;init](auto... items) {
    ((void)(init = fn(std::move(init), items)), ...);
    return init;
  }, a);
};

template&lt;class U, std::size_t N&gt;
static constexpr U accumulate(const std::array&lt;U, N&gt;&amp; u) {
  return accumulate_impl(u, U{},  [](auto&amp;&amp; a, auto&amp;&amp; b){return a+b;});
}

static constexpr auto result = accumulate(arr);

Example here.