C++20 introduced ranges::elements_view
, which accepts a view
of tuple-like values, and issues a view
with a value-type of the Nth element of the adapted view
's value-type, where N is the non-type template parameter.
In [range.elements.view], the synopsis of ranges::elements_view
is defined as:
template<input_range V, size_t N>
requires view<V> && has-tuple-element<range_value_t<V>, N> &&
has-tuple-element<remove_reference_t<range_reference_t<V>>, N> &&
returnable-element<range_reference_t<V>, N>
class elements_view : public view_interface<elements_view<V, N>> {
public:
elements_view() = default;
constexpr explicit elements_view(V base);
// ...
};
Since the constructor of elements_view
only contains the parameter V
, it is impossible to initialize elements_view
directly without specifying all template parameters (godbolt):
std::array<std::tuple<int, float>, 5> r{};
ranges::elements_view<0>{r}; // error: wrong number of template arguments (1, should be 2)
ranges::elements_view<decltype(views::all(r)), 0>{r}; // ok
views::elements<0>(r); // ok
This makes it lose the expression equivalence of other range adaptors such as ranges::transform_view
:
ranges::transform_view{r, [](auto elem) { return std::get<0>(elem); }}; // ok
views::transform(r, [](auto elem) { return std::get<0>(elem); }); // ok
And on the basis of elements_view
, the standard additionally introduces keys_view
and values_view
, which are both aliases for elements_view<views::all_t<R>, N>
:
template <class R>
using keys_view = elements_view<views::all_t<R>, 0>;
template <class R>
using values_view = elements_view<views::all_t<R>, 1>;
The standard gives its use cases in [range.elements#overview-example-2]:
auto historical_figures = map{
{"Lovelace"sv, 1815},
{"Turing"sv, 1912},
{"Babbage"sv, 1791},
{"Hamilton"sv, 1936}
};
auto names = keys_view{historical_figures};
for (auto&& name : names) {
cout << name << ' '; // prints Babbage Hamilton Lovelace Turing
}
which is not quite right since we cannot deduce the type of R
, the only way to construct keys_view
is to specify all template parameters, just like elements_view
:
auto names = std::ranges::keys_view<decltype(std::views::all(historical_figures))>{historical_figures};
So keys_view
and values_view
seem to be completely useless.
What is the purpose of introducing them in the standard? Did I miss some of their useful use cases?