A generic "manual" loop unroller
First, there are some errors that need to be fixed in order for your code to compile:


size_t needs to be std::size_t, or alternatively there needs to be an using std::size_t; declaration.
no matching function for call; you need to specify the template instantiation of the structure based on the "depth" as well as the function:

// WRONG:
unroll&lt;N/2, ForwardIterator, Function&gt;(f, it);
// FIXED:
unroller&lt;N/2&gt;::template unroll&lt;ForwardIterator, Function&gt;(f, it);



From a style perspective, I'd change the order of the template parameters to reflect the order in which the typenames appear in the parameter list (first the Function, then the ForwardIterator).

Then there's one thing that's a bit odd: Functions in the standard library which accept function objects (like std::sort, std::transform, ...) generally accept those function objects by value. This is done (probably) because that allows those functions objects to have mutable state. Your unroller accepts only references to constant function objects. That makes it (a bit) harder to have mutable state in the function object, like when you get one returned by some function:

auto make_that_function_object() {
    bool flag = true;
    return [flag](int n) mutable {
        if (flag) std::cout &lt;&lt; n &lt;&lt; ' ' &lt;&lt; std::flush;
        flag = !flag; };
}


The lambda returned by above function cannot be used with your unroller. To fix it (as a user of your unroller), you need another (non-mutable) lambda which references the original one:

auto original = make_that_function_object();
auto wrapper = [&amp;original](int n) { original(n); };


You could also solve this by accepting non-const references, though I'm not sure whether that's really better. (Accepting the function object by value does not solve the issue because then any changes to the internal state cannot be transferred "back up" the call chain or past "major" iterations of the top level loop.)