在下面的代码中,
values
向量包含由indexes
索引的数据。模板 indexing
允许对像 std::ranges::equal_range
这样的函数进行透明索引,但我没有看到使用范围/投影/视图方法对索引数组(不是值本身!)进行排序的方法。
我能做的是创建一个“旧式”谓词 IndexedValuesComparator
进行排序并将其用于 std::ranges::sort
。
是否有机会在没有谓词的情况下用视图之美来表达相同的内容?这可以像使用
indexing
模板一样完成吗?
正如我所看到的问题,我需要比较值,但是交换索引,而这不能通过仅提供一个实体的视图来完成。有没有简单直接的解决办法?
动机
我需要将许多数组与许多索引绑定,有时需要多个间接级别,所以我希望有一种简短而安全的方式来表达这一点。
#include <vector>
#include <concepts>
#include <ranges>
#include <algorithm>
#include <iostream>
// Reusable generic for the custom view approach
template<typename Index, std::ranges::random_access_range R>
auto indexing(R&& range) {
return std::views::transform([&range](const Index& i) -> decltype(auto) {
return std::ranges::begin(range)[i];
});
};
template<typename Value>
class IndexedValuesComparator {
const std::vector<int>::const_iterator vec;
public:
IndexedValuesComparator(const std::vector<int>::const_iterator& vec) : vec(vec) {}
bool operator() (const auto& lhs, const auto& rhs) {
return vec[lhs] < vec[rhs];
}
};
int main()
{
std::vector<int> values = { 0,30,20,40,10 };
std::vector<int> indexes = { 3,4,2,1,0 };
auto indexing_view = indexes | indexing<int>(values);
std::ranges::sort(indexes, IndexedValuesComparator<int>(values.begin()));
int value_to_search(30);
auto range_pred2 = std::ranges::equal_range(indexing_view, value_to_search);
std::cout << "*range_pred.first = " << *(range_pred2.begin()) << std::endl;
std::cout << "*range_pred.second= " << *(range_pred2.end()) << std::endl;
std::cout << std::endl << "range_pred.second-range_pred.first " << std::distance(range_pred2.begin(), range_pred2.end()) << std::endl;
}
您可以使用变量模板 lambda 来创建自定义投影:
template<typename Index>
auto make_index_proj = []<std::ranges::random_access_range R>(R&& range) {
return [&range](const Index& i) -> decltype(auto) {
return std::ranges::begin(range)[i];
};
};
然后将投影统一传递给
views::transform
和ranges::sort
std::vector<int> values = { 0,30,20,40,10 };
std::vector<int> indexes = { 3,4,2,1,0 };
auto my_proj = make_index_proj<int>(values);
auto indexing_view = indexes | std::views::transform(my_proj);
std::ranges::sort(indexes, {}, my_proj);