C++/STL Prime tuples (twin, cousin, sexy) up to the given limit As I'm mastering STL I wrote a solution for generating all the prime tuples of the form (p1,p2) where "twin" means p2-p1=2, "cousin" p2-p1=4 and "sexy" p2-p1=6.

I'm interested in all the comments about the efficiency and style of this solution.

I use the following subroutine from utilities_template.h to print vector container:

template &lt;class C&gt;
void printContainer(C v, std::string msg = "Container", bool rowWise = true) {
  std::cout &lt;&lt; msg &lt;&lt; " " &lt;&lt; std::endl;
  for (auto it = v.cbegin(); it != v.cend(); ++it)
    std::cout &lt;&lt; std::setw(3) &lt;&lt; *it &lt;&lt; (rowWise ? " " : "\n");
  std::cout &lt;&lt; std::endl;
}


And here is my solution:

#include &lt;iostream&gt;
#include &lt;iterator&gt;
#include &lt;list&gt;
#include &lt;string&gt;
#include &lt;vector&gt;
#include "utilities_template.h"

enum primeClassification { twin = 2, cousin = 4, sexy = 6 };

void removeElementsInListDivisibleByP(int p, std::list&lt;int&gt;&amp; l) {
  l.remove_if([p](int n) { return n % p == 0; });
}

std::vector&lt;int&gt; getAllPrimesLessN(int n, bool debugMode = false) {
  using namespace std;    
  list&lt;int&gt; l;    
  for (int i = 2; i &lt; n + 1; i++) {
    l.push_back(i);
  }    
  int min_element = 2;  //    
  vector&lt;int&gt; primes = {min_element};
  while (min_element != l.back()) {
    removeElementsInListDivisibleByP(min_element, l);
    if (debugMode)
      printContainer(
          l, "After divisible by " + std::to_string(min_element) + " removed:");

    min_element = *std::min_element(l.cbegin(), l.cend());
    primes.push_back(min_element);
  }

  auto temp_it =
      adjacent_find(primes.cbegin(), primes.cend(),
                    [](const int&amp; a, const int&amp; b) { return (b - a) == 1; });

  printContainer(primes, "Primes up to " + std::to_string(n));

  return primes;
}

std::vector&lt;std::pair&lt;int, int&gt; &gt; formPrimePairs(primeClassification pClass,
                                                 std::vector&lt;int&gt;&amp; primes) {
  using namespace std;

  std::vector&lt;std::pair&lt;int, int&gt; &gt; pairs;
  for (auto it = next(primes.cbegin(), 1); it != primes.cend(); it++) {
    if (*it - *std::prev(it, 1) == pClass) {
      auto this_pair = make_pair(*prev(it, 1), *it);
      pairs.push_back(this_pair);
    }
  }

  return pairs;
}

void s4PrimePairs() {
  using namespace std;
  int n = 0;
  cout &lt;&lt; "Please enter the limit: ";
  cin &gt;&gt; n;

  vector&lt;int&gt; primes = getAllPrimesLessN(n);

  printVectorOfPairs(formPrimePairs(primeClassification::twin, primes),
                     "\nTwin pairs (delta=2): ", true);

  printVectorOfPairs(formPrimePairs(primeClassification::cousin, primes),
                     "\nCousin pairs(delta=4): ", true);

  printVectorOfPairs(formPrimePairs(primeClassification::sexy, primes),
                     "\nSexy pairs(delta=6): ", true);
}
std::min_element is unwarranted. The list is initially sorted, and remove_if guarantees to maintain the order of remaining elements. A minimal element is *l.cbegin().
removeElementsInListDivisibleByP is very hard to read. Consider remove_multiples_of_P.
The list initialization loop really wants to be std::iota.
The sieving does work, but it seems less efficient than the classical one.
If an std::vector can be used, it performs better than std::list (mostly due to preferential locality and less memory overhead). You may want to experiment.
I don't see what adjacent_find is supposed to do. Is it a remnant of some debugging code, perhaps?