Sorting multiple vectors based on a reference vector
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.