#include <utility>
#include <cstddef>
#include <vector>
 
using std::size_t;
 
template<typename Lambda>
void for_each_multiset_combo( std::vector<size_t> const& counts, Lambda&& lambda )
{
    if (counts.empty())
    {
        lambda(counts);
        return;
    }
    std::vector<size_t> indexes;
    indexes.reserve( counts.size() );
    while(true) {
        while (indexes.size() < counts.size()) {
            indexes.push_back(0);
        }
        lambda( indexes );
        indexes.back()++;
        while (indexes.back() > counts[indexes.size()-1]) {
            indexes.pop_back();
            if (indexes.empty())
                return; // finished
            indexes.back()++;
        }
    }
}
#include <iostream>
 
int main() {
    std::vector<size_t> multiset = {3, 2, 1, 1};
    size_t counter = 0;
    for_each_multiset_combo( multiset, [&]( std::vector<size_t> const& counts ){
        std::cout << counter << ": [";
        for(auto it = counts.begin(); it != counts.end(); ++it) {
            if (it != counts.begin()) {
                std::cout << ", ";
            }
            std::cout << *it;
        }
        std::cout << "]\n";
        ++counter;
    });
}