У меня есть массив элементов некоторого типа T
.Для некоторой сложной функции я бы хотел отсортировать массив по значению этой функции.Эффективно.
Когда я провел некоторое исследование о том, как это сделать, я быстро обнаружил, что range::v3::sort
из библиотеки range-v3 можно использовать с помощью проекций ,В этом контексте значение T
может быть спроецировано на новое значение, которое будет использоваться компаратором.Проблема в том, что это делается лениво.
Рассмотрим следующий пример:
#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;
}
Здесь T
и f
сохраняются простыми для краткости.Это дает мне вывод:
0 2 4 6 8 1 3 5 7 9 Invocations 60
Но представьте, что f
- это некоторая сложная функция, которую я не хочу выполнять повторно, каждый раз, когда она используется в компараторе (в противном случае я мог бы просто написатьПользовательский компаратор и регулярное использование std::sort
).Я ожидаю, что f
будет вызываться ровно один раз для каждого из значений.Однако после сортировки массива результаты f
могут быть отброшены.
Кроме того, реальные значения самих T
относительно сложны.Я могу быстро поменять два элемента, но мне не следует копировать их в новый временный контейнер (например, std::vector<std::pair<T,int>>
) для сортировки.
Есть ли какой-то краткий подход к этому, кроме ручной сортировки входного массива