C++ for_each_adjacent
template&lt;class Function, class Iterator, unsigned... IntegerSequence&gt;
    auto apply(Function f, Iterator first, std::integer_sequence&lt;unsigned, IntegerSequence...&gt;)
    {
        return f(*std::next(first, IntegerSequence)...);
    }


The Iterator has the requirements of a forward iterator (dereferenceable, forward traversal, multipass).  At the very least, document the iterator type. Also, you should check to make sure the iterator meets the requirements.

The sequence type is too narrow and doesn't support a commonly used sequence like std::index_sequence. 

The sequence helpers are defined in &lt;utility&gt;. Don't rely on latent dependencies from other includes, if you reference it, you should include it.

#include &lt;cstddef&gt;       // std::ptrdiff_t
#include &lt;iterator&gt;      // std::iterator_traits, std::next, std::distance
#include &lt;type_traits&gt;   // std::is_base_of
#include &lt;optional&gt;
#include &lt;utility&gt;       // std::make_integer_sequence
/* ... */

    template&lt;class Function, class ForwardIterator, class Index, Index... Indices&gt;
    auto apply(Function f, ForwardIterator first, std::integer_sequence&lt;Index, Indices...&gt;)
    {
        static_assert(
            std::is_base_of&lt;std::forward_iterator_tag,
                typename std::iterator_traits&lt;ForwardIterator&gt;::iterator_category
            &gt;::value, "");
        return f(*std::next(first, Indices)...);
    }




    template&lt;typename F&gt;
    constexpr const unsigned arg_count_v = arg_count&lt;F&gt;::value;


Programmers typically refer to the number of arguments or operands a function or operation takes as the Arity.

What is the arity of [](auto...){}? What is the arity of [](){} and how does that interact with any subsequent divisions?

Try to be consistent with your naming.  While F is commonly Function, you kinda bounce between the two.  Pick one and be consistent.



//Returns a pointer to the remainder values or the end or nullptr
template&lt;class Iterator,class Function&gt;
auto for_each_adjacent(Iterator begin,Iterator end,Function func)
-&gt; std::optional&lt;typename std::iterator_traits&lt;Iterator&gt;::pointer&gt;


Adjacents work like a sliding window, where each subsequent window starts at an offset of 1 from the first element in the previous window, e.g. 

$$
[1, 2], [2, 3], [3, 4], ...
$$  

The behavior you have implemented is a window over chunk sizes, incrementing from the last element in the previous window instead of the first, e.g.

$$
[1, 2], [3, 4], [5, 6], ...
$$

and some remainder less than the the length.  Consider renaming this function to a name that better represents its action, (for_each_chunked?).

Reading your comment, why not just return std::optional&lt;Iterator&gt; or the Iterator itself? After the calls, begin will always point to the first element in the remaining chunk or end.  The user can check if the returned iterator is at end.



    using value_type = typename std::iterator_traits&lt;Iterator&gt;::value_type;
    const value_type length = std::distance(begin,end);


This doesn't make sense. Iterator::value_type is the type of the values that can be obtained by dereferencing the iterator.  std::list&lt;std::string&gt;::iterator::value_type is std::string.  Just use auto and let std::distance provide the correct type (iterator::difference_type, or std::ptrdiff_t).

    const auto length = std::distance(begin, end);




    const std::ptrdiff_t remainder = length % detail::arg_count_v&lt;Function&gt;;
    for (auto d = length; d &gt;= detail::arg_count_v&lt;Function&gt;; d -= detail::arg_count_v&lt;Function&gt;)
        detail::apply(func,(end - d),std::make_integer_sequence&lt;unsigned,detail::arg_count_v&lt;Function&gt;&gt;());

return (remainder) ? std::make_optional(end - remainder) : std::nullopt;


Instead of trying to figure out if their are enough elements remaining to call a function by arity, just calculate the number of chunks you are going to call f with.  Integral division has the nice property of truncating the remainder.

    auto chunks = length / detail::arg_count_v&lt;Function&gt;;


If you really want the remainder

    auto [chunks, remainder] = std::div(length, detail::arg_count_v&lt;Function&gt;);


Then you just loop on that count.

    constexpr auto indices = std::make_index_sequence&lt;detail::arg_count_v&lt;Function&gt;{};

    while (chunks--) {
        detail::apply(func, begin, indices);
        std::advance(begin, detail::arg_count_v&lt;Function&gt;);
    }

    return begin;


An added benefit it that you can keep supporting forward iterators (std::advance) instead of elevating the requirement to random access iterators (end - d, end-remainder).




  I am not sure to pass in a epilogue function for the remaining variables


Does your use-case require you to have the entire range consumed by functions?  Let the caller decide what to do and just return an iterator.