Как перебирать неупорядоченные пары внутри неупорядоченного множества?

каков краткий способ итерации на неупорядоченных парах элементов в unordered_set?

(поэтому порядок не имеет значения, и элементы должны быть разными)

например,{1, 2, 3} => (1, 2) (2, 3) (1, 3)

мои первоначальные попытки были чем-то вроде

for (i = 0; i < size - 1; i++) {
  for (j = i + 1; j < size; j++) {
    ...
  }
}

но это не очень удобно с итераторами.

2 ответов


это должно работать, учитывая std::unordered_set s:

auto set_end = s.end();
for (auto ai = s.begin(); ai != set_end; ++ai) {
    for (auto bi = std::next(ai); bi != set_end; ++bi) {
        // *ai, *bi
    }
}

это в основном итераторный эквивалент следующего в целых числах:

for (int i = 0; i < n; ++i) {
    for (int j = i + 1; j < n; ++j) {
        // i, j
    }
}

вот решение orlp в полу-родовой форме.

template<typename ForwardIterator, typename DestItr>
auto cartesian_product(ForwardIterator b, ForwardIterator e, DestItr d) -> DestItr {
    using std::next;
    using std::for_each;
    for (; b != e; ++b) {
        for_each(next(b), e, [&](auto right){
            *d++ = std::make_tuple(*b, right);
        });
    }
    return d;
}

template<typename ForwardRange, typename DestItr>
auto cartesian_product(ForwardRange r, DestItr d) -> DestItr {
    using std::begin;
    using std::end;
    return cartesian_product(begin(r), end(r), d);
}

жить на Coliru.

вы могли бы, конечно, сделать его более общим, имея перегрузки для пользовательских функторов вместо make_tuple и оператор присваивания. Стандартные библиотечные алгоритмы, как правило, делают это. Если бы я писал это для библиотеки, то, вероятно, сделал бы то же самое.