Classificação de containers zipados (bloqueados) em C ++ usando boost ou o STL

O que eu quero fazer: Eu quero ordenar 2, ou 3, ou N vetores, juntos,sem copiá-los em uma tupla. Ou seja, deixando a verbosidade de lado, algo como:

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;

Isso deve resultar:

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

Como estou fazendo agora: Eu implementei o meu próprio quicksort, onde o primeiro array que eu passo é usado para a comparação, e as permutações são aplicadas a todos os outros arrays. Eu simplesmente não consegui descobrir como reutilizar o std :: sort para o meu problema (por exemplo, permutações de extração).

O que eu tentei: boost :: zip_iterator eboost :: zip_range (com boost :: combine range), mas std :: sort eboost :: range :: algoritmo :: sort Reclamar que os iteradores / intervalos são somente leitura e não acesso aleatório ...

Questão: Como classifico N vetores na etapa de bloqueio (zipada)? O problema parece bastante genérico e comum, então eu acho que deve haver uma solução fácil através de uma biblioteca provavelmente muito complexa, mas eu simplesmente não consigo encontrá-lo ...

Observações: sim, existem questões semelhantes no stackoverflow, esta pergunta é feita muito em diferentes formas. No entanto, eles sempre são fechados com uma das seguintes respostas:

Copie seus vetores em um par / tupla e classifique essa tupla ...Copie seus vetores em uma estrutura com um membro por vetor e classifique um vetor de estruturas ...Implemente sua própria função de classificação para seu problema específico ...Use uma matriz auxiliar de índices ...Use boost :: zip_iterator sem um exemplo ou com um exemplo que produz resultados ruins.

Dicas:

Eu encontrei este segmento noaumentar lista de discussão que aponta para issopapel de Anthony Williams. Embora isso pareça funcionar apenas para pares, eles também discusam um TupleIteratorType, mas não consegui encontrá-lo.user673679 encontradoisto post contendo uma boa solução para o caso de dois contêineres. Também fixa o problema (a ênfase é minha):

[...] o problema fundamental é que "pares" de referências de matriz não se comportam como deveriam [...] eu simplesmente decidi abusar da notação de um iterador e escrever algo que funciona. Isso envolveu escrever, efetivamente, um iterador não-conformea referência do tipo de valor não é igual ao tipo de referência.

Responda: veja o comentário por interjay abaixo (isso também responde parcialmentepergunta futura):

#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;
}

Pergunta futura: a resposta anterior funciona para contêineres de seqüência. Poderíamos conseguir também trabalhar emclassificável recipientes (por exemplo, sequências e listas)? Isso exigiria random_access e TupleIterators bidirecionais, bem como um algoritmo de classificação que funciona em iteradores bidirecionais.

Atualizar: isso funciona para combinações de contêineres semelhantes a seqüência. No entanto, misturar uma lista exigiria que o std :: sort suportasse BidirectionalIterators (o que não é o caso).

questionAnswers(5)

yourAnswerToTheQuestion