Сортировка заархивированных (заблокированных) контейнеров в C ++ с использованием boost или STL

Что я хочу сделать: Я хочу отсортировать 2, 3 или N векторов, соединенных вместе,не копируя их в кортеж. То есть, оставляя в стороне многословие, что-то вроде:

vector<int>    v1 = {  1,   2,   3,   4,   5};
vector<double> v2 = { 11,  22,  33,  44,  55};
vector<long>   v3 = {111, 222, 333, 444, 555};

typedef tuple<int&,double&,long&> tup_t;
sort(zip(v1,v2,v3),[](tup_t t1, tup_t t2){ return t1.get<0>() > t2.get<0>(); });

for(auto& t : zip(v1,v2,v3))
  cout << t.get<0>() << " " << t.get<1>() << " " << t.get<2>() << endl;

Это должно вывести:

5 55 555
4 44 444
...
1 11 111

Как я это делаю прямо сейчас: Я реализовал свою собственную быструю сортировку, где первый массив, который я передаю, используется для сравнения, а перестановки применяются ко всем другим массивам. Я просто не мог понять, как повторно использовать std :: sort для моей задачи (например, извлечь перестановки).

Что я попробовал: повышение :: zip_iterator а такжеповышение :: zip_range (с бустом :: объединить диапазон), но оба типа std :: sort иповышение :: Диапазон :: алгоритм :: сортировать жалуются, что итераторы / диапазоны только для чтения, а не произвольного доступа ...

Вопрос: Как отсортировать N векторов в шаге блокировки (в архиве)? Проблема выглядит довольно общей и общей, так что я думаю, должно быть простое решение с помощью, вероятно, очень сложной библиотеки, но я просто не могу ее найти ...

Примечания: да, в stackoverflow есть похожие вопросы, этот вопрос часто задают в разных формах. Однако они всегда закрыты с одним из следующих ответов:

Скопируйте ваши векторы в пару / кортеж и сортируйте этот кортеж ...Скопируйте ваши векторы в структуру с одним членом на вектор и сортируйте вектор структур ...Реализуйте свою собственную функцию сортировки для вашей конкретной проблемы ...Использовать вспомогательный массив индексов ...Используйте boost :: zip_iterator без примера или с примером, который дает плохие результаты.

подсказки:

Я нашел эту тему вувеличить список рассылки что указывает на этобумага от Энтони Уильямса. Хотя кажется, что это работает только для пар, они также обсуждают TupleIteratorType, но я не смог его найти.user673679 нашелэто пост, содержащий хорошее решение для двух контейнеров. Это также решает проблему (акцент мой):

[...] фундаментальная проблема заключается в том, что «пары» ссылок на массивы ведут себя не так, как должны [...] Я просто решил злоупотребить нотацией итератора и написать что-то, что работает. Это включало в себя написание несоответствующего итератора, гдессылка типа значения не совпадает с типом ссылки.

Ответ: см. комментарий от interjay ниже (это также частично отвечаетбудущий вопрос):

#include "tupleit.hh"
#include <vector>
#include <iostream>
#include <boost/range.hpp>
#include <boost/range/algorithm/sort.hpp>
#include <boost/range/algorithm/for_each.hpp>

template <typename... T>
auto zip(T&... containers)
    -> boost::iterator_range<decltype(iterators::makeTupleIterator(std::begin(containers)...))> {
  return boost::make_iterator_range(iterators::makeTupleIterator(std::begin(containers)...),
                                      iterators::makeTupleIterator(std::end(containers)...));
}

int main() {

  typedef boost::tuple<int&,double&,long&> tup_t;

  std::vector<int>    a = {   1,   2,   3,   4 };
  std::vector<double> b = {  11,  22,  33,  44 };
  std::vector<long>   c = { 111, 222, 333, 444 };

  auto print = [](tup_t t){ std::cout << t.get<0>() << " " << t.get<1>() << " " << t.get<2>() << std::endl; };

  boost::for_each( zip(a, b, c), print);

  boost::sort( zip(a, b, c), [](tup_t i, tup_t j){ return i.get<0>() > j.get<0>(); });

  for ( auto tup : zip(a, b, c) ) print(tup);

  return 0;
}

Будущий вопрос: предыдущий ответ работает для контейнеров последовательности. Можем ли мы заставить его работатьсортировка контейнеры (например, последовательности и списки)? Для этого потребуются random_access и двунаправленные TupleIterators, а также алгоритм сортировки, который работает на двунаправленных итераторах.

Обновить: это работает для комбинаций последовательных контейнеров. Однако для смешивания списка потребуется, чтобы std :: sort поддерживал BidirectionalIterators (чего нет).

Ответы на вопрос(5)

Ваш ответ на вопрос