Quick Sort Implementation with iterators Most quicksort examples online use C-style arrays and indexes. I have written below quicksort implementation with STL style iterators. It looks fine to me, but I feel like I may be making more than necessary copies of iterators. I am open for any suggestions/improvements:

#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;cassert&gt;
#include &lt;algorithm&gt;
#include &lt;iterator&gt;

template &lt;typename Iter&gt;
inline Iter partition(const Iter&amp; beg, const Iter&amp; end) {
  using std::swap;
  assert(beg != end);
  auto piv = end;
  --piv; // Pivot is the last element
  auto index_small = beg;

  for (auto index_large = beg; index_large != piv; ++index_large) {
    if (*index_large &lt;= *piv) {
      swap(*index_large, *index_small);
      ++index_small;
    }
  }
  swap(*index_small, *piv);
  return index_small;
}

template &lt;typename Iter&gt;
void quick_sort(const Iter&amp; beg, const Iter&amp; end) {
  if (end - beg &gt; 1) {
    const auto&amp; piv = partition(beg, end);
    quick_sort(beg, piv);
    quick_sort(piv, end);
  }
}

// Test
int main() {
  std::vector&lt;int&gt; vec{ 19, 54, 53, 9, 3, 96, 40, 36, 96, 43, 45,
                        78, 57, 6, 12, 100, 36, 15, 27, 45, 80, 39,
                        10, 71, 100, 15, 41, 43, 20, 32, 61, 2, 55,
                        33, 85, 32, 11, 50, 25, 17, 75, 74, 39, 49,
                        50, 17, 18, 55, 63, 81, };
  quick_sort(vec.begin(), vec.end());
  std::copy(vec.begin(), vec.end(), std::ostream_iterator&lt;int&gt;(std::cout, " "));
  std::cout &lt;&lt; '\n';
}
You have done a great job.  Here’s my suggestions:


Sort the include directives in alphabetical order. 
Instead of using the generic name Iter, it may be a good idea to express the random access requirement: something like RandomIt. 
Iterators should be passed by value, not const reference.  Don’t be afraid to copy iterators — they are intended to be lightweight objects that are frequently copied, and passing them by const reference will incur overhead over passing them by value because of the additional indirection. 
It is more logical to use auto piv = std::prev(end);, because int y = x - 1; is more logical then int y = x; --y;, right?  (Of course you can use end - 1, but that may be less efficient if the subtraction operator of the iterator isn’t inlined.)
You can use std::iter_swap instead of manually ADL’ing swap. 
Instead of enforcing &lt;=, consider taking a custom comparator as the standard algorithms do.  (Also note that the standard library facilities always use &lt; as the comparator by default.  &lt;= is not required unless you provide a custom comparator.)


Also, always choosing last element as the pivot can make the code vulnerable to reversely sorted sequences.  You can consider taking a random number generator to randomize the choice if this becomes a problem.