Merge adjacent occurrences of identical elements in data collection
Generally looks okay (though I would prefer shorter line lengths, and the indentation needs cleaning up).

It seems that we've focused on using std::back_insert_iterator as the output iterator; this leads to a couple of problems that are visible when we switch to a different iterator, such as a collection iterator or raw pointer:


The caller doesn't know where the output finished; we should return the final value of out, just as std::unique_copy() does.
The assignment out = neither indirects nor advances the iterator; it should be *out++ =.


We don't need a separate start copied from first, and we can use std::adjacent_find to determine the range of equal elements:

#include &lt;algorithm&gt;
#include &lt;functional&gt;
#include &lt;numeric&gt;

template &lt;typename ForwardIterator, typename OutputIterator,
          typename Equal, typename Merge&gt;
OutputIterator merge_adjacent(ForwardIterator first, ForwardIterator last,
                              OutputIterator out,
                              Equal equal, Merge merge)
{
    while (first != last) {
        auto stop = std::adjacent_find(first, last, std::not_fn(equal));
        if (stop != last) {
            // advance to include the first of the pair
            ++stop;
        }
        *out++ = std::accumulate(first+1, stop, *first, merge);
        first = stop;
    }

    return out;
}


This version still performs two passes (one for the search, and one for the accumulate).  The commented-out, lower-level version of the function should be able to accept input iterators, as a single-pass algorithm.

Looking at that version, there's only a little to improve.  I'd probably post-increment the iterators while dereferencing, rather than as a separate statement, but that's just a style preference.  One thing I would change would be to use std::move() when finishing with next, to minimise unnecessary copying:

#include &lt;algorithm&gt;
#include &lt;numeric&gt;
#include &lt;utility&gt;

template &lt;typename InputIterator, typename OutputIterator,
          typename Equal, typename Merge&gt;
OutputIterator merge_adjacent(InputIterator first, InputIterator last,
                              OutputIterator out,
                              Equal equal, Merge merge)
{
    while (first != last) {
        auto next = *first++;
        while (first != last &amp;&amp; equal(next, *first)) {
            next = merge(std::move(next), *first++);
        }
        *out++ = std::move(next);
    }

    return out;
}