Is std::views::values supposed to work with std::map?

Viewed 114

The C++20 ranges library includes some (in my opinion) amazing features. For example I really started to like the std::views::keys and std::views::values range adaptors, that simplify iterating over the keys or values of a map. While previously one needed to do something like

std::map<int, int> m {{1,1}, {2,2}, {3,3}};
...
for ( auto&& e : m ) {
    auto v = e.second;
    // use v
}

With C++20 you can do the same a lot more elegantly:

for ( auto v : std::views::values(m) ) {
    // use v
}

At least, that is what I though was possible and probably an intended use case of std::views::values. I recently discovered that clang-14/13/12 does not compile the second version in contrast to gcc-12/11/10 and msvc-19.32 (overview on godbolt).

What am I missing here? Is the code above valid C++20 or is clang right about refusing to compile it?

Edit:
I also noticed, that clang does not consider std::map to be a std::ranges::viewable_range. But I do not see why clangs std::map should behave different from gcc's std::map in a standard library function.

1 Answers

The cppreference page on std::views::values shows this usecase: a std::map<char, int> being piped into std::views::values.

Furthermore, it explicitly says

Note

values_view can be useful for extracting values from associative containers, e.g. for (auto const& value : std::views::values(map)) { /*...*/ }.

Therefore, if your example doesn't work, it's either a bug or a missing, yet to implement, feature in the compiler.

Unless one thinks that cppreference's Note is wrong, which I don't.

Related