I have an array of element of some type T
. For some complex function I would like to sort the array by the value of that function. Efficiently.
When I did some research on how to do such a thing, I quickly found that range::v3::sort
, from the range-v3 library, could be used with the help of projections. In that context, the value T
can be projected onto a new value to be used by a comparator. The problem is, that it is done lazily.
Consider the following example:
#include <range/v3/algorithm/sort.hpp>
#include <vector>
#include <iostream>
int main() {
int invocations=0;
std::vector<int> data{1,5,2,7,6,3,4,8,9,0};
auto f = [&](int val){
++invocations;
return val%2 ? val+100 : val;
};
ranges::v3::sort(data, std::less<int>{}, f);
for (int v : data) {
std::cout << v << ' ';
}
std::cout << "Invocations " << invocations << std::endl;
}
Here T
and f
are kept simple for the sake of brevity. This gives me the output:
0 2 4 6 8 1 3 5 7 9 Invocations 60
But envision that f
is some complex function that I do not want to be executed repeatedly, each time it is used in the comparator (otherwise I could just write a custom comparator and use regular std::sort
). I would expect f
to be called exactly once for each of the values. However, once the array is sorted, the results of f
can be discarded.
Also, the real values of T
themselves are relatively complex. I can quickly swap two elements around, but I shouldn't copy them into a new, temporary container (e.g. std::vector<std::pair<T,int>>
) for sorting.
Is there some brief approach to that, besides manually sorting my input array?