Sorting multiple vectors based on a reference vector I am trying to sort vectors based on a reference vector. First I am getting the indexes for the reference vector and then using that I am doing inplace sorting for the rest of the vectors.

#include &lt;vector&gt;
#include &lt;cassert&gt;
#include &lt;iostream&gt;
#include &lt;algorithm&gt;

using iter = std::vector&lt;int&gt;::iterator;
using order_type = std::vector&lt;std::pair&lt;size_t, iter&gt;&gt;;

void create_permutation(order_type &amp;order)
{
        struct ordering {
                bool operator ()(std::pair&lt;size_t, iter&gt; const&amp; a, std::pair&lt;size_t, iter&gt; const&amp; b) {
                        return *(a.second) &lt; *(b.second);
                }
        };

        std::sort(order.begin(), order.end(), ordering());
}

void reorder(std::vector&lt;int&gt; &amp;vect, order_type index)
{
        for (int i=0; i&lt; vect.size(); i++)
        {
                while (index[i].first != i)
                {
                        int  old_target_idx  = index[index[i].first].first;
                        int old_target_v  = vect[index[i].first];

                        vect[index[i].first] = vect[i];
                        index[index[i].first].first = index[i].first;

                        index[i].first = old_target_idx;
                        vect[i]   = old_target_v;
                }
        }
}

template&lt;typename... argtype&gt;
void sort_from_ref(argtype... args);

template&lt;typename T, typename A, typename... argtype&gt;
void sort_from_ref(order_type order, std::vector&lt;T,A&gt; &amp;vect, argtype &amp;&amp;...args)
{
        reorder(vect, order);
        sort_from_ref(order, std::forward&lt;argtype&gt;(args)...);
}

template&lt;&gt;
void sort_from_ref(order_type order, std::vector&lt;int&gt; &amp;vect) {
        reorder(vect, order);
}

int main()
{
        size_t n = 0;
        std::vector&lt;int&gt; vect_1{ 1, 0, 2, 3 };
        std::vector&lt;int&gt; vect_2{ 100, 200, 300, 400 };
        std::vector&lt;int&gt; vect_3{ 100, 200, 300, 400 };
        std::vector&lt;int&gt; vect_4{ 400, 200, 3000, 4000 };
        std::vector&lt;int&gt; vect_5{ 500, 200, 360, 400 };
        order_type order(vect_1.size());

        for (iter it = vect_1.begin(); it != vect_1.end(); ++it) {
                order[n] = std::make_pair(n, it);
                n++;
        }
        create_permutation(order);
        sort_from_ref(order, vect_2, vect_3, vect_4, vect_5);

        {
                std::vector&lt;int&gt; test{200, 100, 300, 400};
                assert(vect_2 == test);
        }
        {
                std::vector&lt;int&gt; test{200, 100, 300, 400};
                assert(vect_3 == test);
        }
        {
                std::vector&lt;int&gt; test{200, 400, 3000, 4000};
                assert(vect_4 == test);
        }
        {
                std::vector&lt;int&gt; test{200, 500, 360, 400};
                assert(vect_5 == test);
        }

        return 0;
}
For another take on the same problem (sorting parallel arrays), see Quicksort template (for sorting corresponding arrays).

Your code is strangely organized. I would expect it to have a single entry point, something like this:

template&lt;class Vector, class... Vectors&gt;
void parallel_sort(Vector&amp; keyvector, Vectors&amp;... vectors) {
    std::vector&lt;size_t&gt; order(keyvector.size());
    std::iota(order.begin(), order.end(), 0);
    std::sort(order.begin(), order.end(), [&amp;](size_t a, size_t b) {
        return keyvector[a] &lt; keyvector[b];
    });
    (reorder(keyvector, order) , ... , reorder(vectors, order));
}


(Hey, look at that! It's a complete implementation, except for the reorder function you already wrote!)

But instead you require the calling code to set up their own order vector manually, then call create_permutation, then sort_from_ref, in that order. That's a lot of steps. At the very least, you could provide a function create_order_vector to simplify that first step.



The one advantage I can see to requiring the caller to provide the order vector is that it allows your library code to do no heap allocations. Vice versa, a problem with my code above is that it requires O(n) memory to sort n elements. If I have a million-element vector, I need to heap-allocate another eight million bytes to sort it! That could be annoying or prohibitive for some callers — they might not expect a sorting function to throw std::bad_alloc. At least by making the caller allocate the eight million bytes themselves, you're putting the issue front and center where they can't miss it.



I think it's strange that you define the alias order_type to be std::vector&lt;std::pair&lt;size_t, iter&gt;&gt;. I would rather see

using order_type = std::pair&lt;size_t, iter&gt;;

[...] std::vector&lt;order_type&gt; order;


Again, I guess it comes down to my wanting to see std::vector-ness explicitly in the code. I have the same complaint about typedefs such as using Foo = foo*; that hide a type's pointer-ness.



template&lt;typename T, typename A, typename... argtype&gt;
void sort_from_ref(order_type order, std::vector&lt;T,A&gt; &amp;vect, argtype &amp;&amp;...args)
{
        reorder(vect, order);
        sort_from_ref(order, std::forward&lt;argtype&gt;(args)...);
}


In C++17, you can use a comma-operator fold-expression to do this, as I did above. But even in C++11, you can use a pack expansion to do this without all the "recursive template" stuff. (See "Iteration is better than recursion.") You'd just do something like this:

template&lt;class... Args&gt;
void sort_from_ref(order_type order, Args&amp;... args)
{
    int dummy[] = {
        [&amp;]() { reorder(args, order); return 0; } ...
    };
}


Notice that I also changed argtype to Args. It's a pack of multiple argtypes, not just one; and the C++ convention for template parameters is to CamelCase them.

I also eliminated your perfect forwarding. We know that all our args are going to be non-const lvalue references; so we should just say so.

We also know that all our args are going to be std::vector&lt;T&gt; for some T, because that's the only kind of argument that will be accepted by our reorder template. Therefore, it is incorrect (but largely harmless) that you wrote 

template&lt;typename T, typename A, [...]&gt;
void sort_from_ref([...] std::vector&lt;T,A&gt; &amp;vect, [...]


because there is only one possible A that can go there and have the code still compile. You should just have said

template&lt;typename T, typename... argtype&gt;
void sort_from_ref(order_type order, std::vector&lt;T&gt;&amp; vect, argtype&amp;&amp;... args)


(except that, as we've seen, you don't need this "recursive" template at all).



No comment on your reorder function; that part is all math. (Does it work? Did you test it exhaustively?)

Okay, two comments...

                    index[i].first = old_target_idx;
                    vect[i]   = old_target_v;


Your whitespace here (and other places) is wonky. It looks like maybe you were trying to align the = signs, but failed? I strongly recommend not trying to align anything, ever. It's not robust against refactoring. (For example, if you change the name of a variable, now you have to realign everything it touched.)

for (int i=0; i&lt; vect.size(); i++)


You should be getting a stupid warning from your compiler about "comparing signed and unsigned" here. If you're not, then turn up your warning levels — you should be using -W -Wall (and maybe -Wextra) on non-MSVC compilers, and I'd say -W4 on MSVC. The traditional workaround would be to make i a size_t instead of an int.