std::multimap equal _range 和 C++20 std::views::values 不能很好地协同工作

std::multimap equal _range and C++20 std::views::values do not work nicely together

我有以下代码,它可以工作,但 C++20 版本看起来并不比 C++17 版本好多少。我的猜测问题是 multimap equal_range returns a pair and ranges 无法确定这是一对有效的迭代器。

有没有办法用更短更好的方式来写这个?

#include <iostream>
#include <map>
#include <ranges>

int main() {
    std::multimap<bool,int> oddness{{false,2}, {true,3}, {true,47}, {false,74656}};
    // nice, does not work:
    // oddness.equal_range(true) | std::views::values;
    // works:
    oddness | std::views::values;

    // working code:
    auto odds = oddness.equal_range(true);
    const auto odds_view = std::views::values(std::ranges::subrange(odds.first, odds.second));
    for (const auto& odd : odds_view) {
        std::cout << odd << std::endl;
    }
}

问题是 equal_range return 是一个 pair<It, It>,(不幸的是)它本身不是一个范围。在我看来,这是更不幸的遗留 API 决定之一 - 因为我们有这个优秀的名字,但它做了一些......不太好。

您过去可以使用 pair<It, It> 并轻松将其转换为 subrange,但这不一定有效并已被删除(首先在 LWG3281 and then the rest in LWG3404 中)。并非所有的迭代器对实际上都是范围(一些算法 return 两个迭代器不是 - 如 minmax_elementmismatch)。

不过没关系,我们可以自己写一个显式的:

struct pair_to_range_t {
    template <typename I>
    friend constexpr auto operator|(std::pair<I, I> const& pr, pair_to_range_t) {
        return std::ranges::subrange(pr.first, pr.second);
    }
};

inline constexpr pair_to_range_t pair_to_range{};

然后你可以写:

oddness.equal_range(true) | pair_to_range | std::views::values;