Create all combinations of length N from a given alphabet (2) I implemented this challenge in Java before but performance was not the best so I decided to implement this in C++ to compare the two. The code works and performance is indeed much better than in the Java version. However I am unsure about the quality of this code.
I am still not overly familiar with modern C++ and would like to know if there is anything that I am doing awfully wrong.
Challenge description:

You are given a number N and a string S. Print all of the possible ways to write a string of length N from the characters in string S, comma delimited in alphabetical order.
The first argument will be the path to the input filename containing the test data. Each line in this file is a separate test case. Each line is in the format: N,S i.e. a positive integer, followed by a string (comma separated). E.g.
Print all of the possible ways to write a string of length N from the characters in string S comma delimited in alphabetical order, with no duplicates.
Input sample:
1,aa
2,ab
3,pop

Output sample:
a
aa,ab,ba,bb
ooo,oop,opo,opp,poo,pop,ppo,ppp


Code:
#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;string&gt;
#include &lt;fstream&gt;
#include &lt;algorithm&gt;
#include &lt;sstream&gt;
#include &lt;iterator&gt;

void generate_words(const std::vector&lt;char&gt; &amp;alphabet, size_t &amp;word_length, std::vector&lt;std::string&gt; &amp;results)
{
    std::vector&lt;size_t&gt; index(word_length, 0);

    for (;;)
    {
        std::string word(index.size(), ' ');
        for (size_t i = 0; i &lt; index.size(); ++i)
        {
            word[i] = alphabet[index[i]];
        }
        results.emplace_back(word);

        for (int i = index.size() - 1; ; --i)
        {
            if (i &lt; 0)
            {
                return;
            }

            ++index[i];

            if (index[i] == alphabet.size())
            {
                index[i] = 0;
            }
            else
            {
                break;
            }
        }
    }
}

int main(int argc, char **argv)
{
    std::ifstream infile(argv[1], std::ios::in | std::ifstream::binary);

    std::string line;
    while (infile.good() &amp;&amp; getline(infile, line))
    {
        size_t word_length = std::stoi(line.substr(0, line.find(',')));
        std::string letters = line.substr(line.find(',') + 1);

        std::vector&lt;char&gt; alphabet;
        for (const auto &amp;it : letters)
        {
            alphabet.push_back(it);
        }
        std::sort(alphabet.begin(), alphabet.end());
        auto last = std::unique(alphabet.begin(), alphabet.end());
        alphabet.erase(last, alphabet.end());

        std::vector&lt;std::string&gt; results;
        generate_words(alphabet, word_length, results);

        std::ostringstream result_line;
        std::copy(results.begin(), results.end() - 1, std::ostream_iterator&lt;std::string&gt;(result_line, &quot;,&quot;));
        result_line &lt;&lt; results.back();

        std::cout &lt;&lt; result_line.str() &lt;&lt; &quot;\n&quot;;
    }
}
The generate_words code looks pretty good to me.

Actually, one minor thing - you can return the vector as opposed to passing out by reference. You won't get a performance hit (see move semantics), and it'll make the function easier to use:

auto words = generate_words(letters, word_length);


Some minor observations about the code in main:

1 - As a general rule, you should allocate a vector's memory up front if you know how many elements it will contain. This prevents reallocations from occurring when new elements are inserted into the vector. std::vector provides the reserve method for doing this:

std::vector&lt;char&gt; alphabet;
// allocate memory for at least letter.size() chars
alphabet.reserve(letters.size());
for (const auto &amp;it : letters)
{
    // now you don't have to worry about reallocations happening
    // here
    alphabet.push_back(it);
}


See:

What happens under the hood of vector::push_back memory wise?

std::vector push_back is bottleneck

vector::reserve example code

In this case, you can skip the loop entirely by using std::vector's iterator constructor:

std::vector&lt;char&gt; alphabet(letters.begin(), letters.end());


2 - If you're not using the variable 'letters' after it's been initialized, you could do your sort/unique operation in place:

std::sort(letters.begin(), letters.end());
letters.erase(std::unique(letters.begin(), letters.end()), letters.end());


and then pass letters to generate_words() (you'd have to change the first parameter to a string)