如何使用C++20中的std::views特性对向量进行排序?

4
我想以排序的方式遍历一个向量,而不修改底层的向量。是否可以使用std::views和/或std::range来实现?
我已经成功地使用views实现了过滤,但我不知道是否可能使用谓词进行排序。
您可以在此处找到一个完整的示例:https://godbolt.org/z/cKer8frvq
#include <iostream>
#include <ranges>
#include <vector>
#include <chrono>

struct Data{
    int a;
};

int main() {

    std::vector<Data> vec = {{1}, {2}, {3}, {10}, {5}, {6}};
  
    auto sortedView = // <= can we use std::views here ?
                           
    for (const auto &sortedData: sortedView) std::cout << std::to_string(sortedData.a) << std::endl; // 1 2 3 5 6 10

    for (const auto &data: vec) std::cout << std::to_string(data.a) << std::endl; // 1 2 3 10 5 6
}

2
[OT]:std::to_string 是不必要的,std::cout << data.a 是正确的。 - Jarod42
这个向量可以容纳约1GB的数据...所以我宁愿不复制它。 - Victor
1个回答

7
你需要修改一些东西才能使用std::ranges::sort(或std::sort),但它不一定是你实际的数据。
#include <iostream>
#include <ranges>
#include <numeric>
#include <algorithm>
#include <vector>
#include <chrono>

struct Data{
    int a;
    friend auto operator<=> (const Data &, const Data &) = default;
};

int main() {

    std::vector<Data> vec = {{1}, {2}, {3}, {10}, {5}, {6}};

    std::vector<std::size_t> indexes(vec.size());
    std::iota(indexes.begin(), indexes.end(), std::size_t{ 0 }); // 0z in C++23

    auto proj = [&vec](std::size_t i) -> Data & { return vec[i]; };

    std::ranges::sort(indexes, std::less<>{}, proj);
  
    auto sortedView = std::ranges::views::transform(indexes, proj);
                           
    for (const auto &sortedData: sortedView) std::cout << sortedData.a << std::endl; // 1 2 3 5 6 10

    for (const auto &data: vec) std::cout << data.a << std::endl; // 1 2 3 10 5 6
}

你能详细解释一下这行代码吗?:auto proj = [&vec](std::size_t i) -> Data & { return vec[i]; }; - Victor
@Victor:请查看lambda(带有捕获和尾随返回类型)。 - Jarod42
@Jarod42 我现在不理解的是 Data & { return vec[i]; } 的返回类型。 - Victor
@Victor:-> Data& 是尾随返回类型(如果没有它,它将通过值返回)。 - Jarod42

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接