keys_view
example is brokenSection: 25.7.23.1 [range.elements.overview] Status: C++23 Submitter: Barry Revzin Opened: 2021-05-29 Last modified: 2023-11-22
Priority: 3
View all issues with C++23 status.
Discussion:
In 25.7.23.1 [range.elements.overview] we have:
[Example 2:
keys_view
is an alias forelements_view<views::all_t<R>, 0>
, and is useful for extracting keys from associative containers.auto names = keys_view{historical_figures}; for (auto&& name : names) { cout << name << ' '; // prints Babbage Hamilton Lovelace Turing }— end example]
Where keys_view
is defined as:
template<class R> using keys_view = elements_view<views::all_t<R>, 0>;
There's a similar example for values_view
.
keys_view(r)
cannot deduce R
—
it's a non-deduced context. At the very least, the example is wrong and should be rewritten as
views::keys(historical_figures)
. Or, I guess, as
keys_view<decltype(historical_figures)>(historical_figures)>
(but really, not).
[2021-05-29 Tim comments and provides wording]
I have some ideas about making CTAD work for keys_view
and
values_view
, but current implementations of alias template CTAD are
not yet in a shape to permit those ideas to be tested.
What is clear, though, is that the current definitions of keys_view
and values_view
can't possibly ever work for CTAD, because R
is only
used in a non-deduced context and so they can never meet the "deducible" constraint in
12.2.2.9 [over.match.class.deduct] p2.3.
views::all_t
transformation
in those alias templates. This makes these aliases transparent enough to support CTAD out
of the box when a view is used, and any questions about deduction guides on
elements_view
can be addressed later once the implementations become more mature.
This also makes them consistent with all the other views: you can't write
elements_view<map<int, int>&, 0>
or
reverse_view<map<int, int>&>
, so why do we allow
keys_view<map<int, int>&>
? It is, however, a breaking change,
so it is important that we get this in sooner rather than later.
The proposed resolution has been implemented and tested.
[2021-06-14; Reflector poll]
Set priority to 3 after reflector poll in August. Partially addressed by an editorial change.
Previous resolution [SUPERSEDED]:
This wording is relative to N4885.
Modify 25.2 [ranges.syn], header
<ranges>
synopsis, as indicated:[…] namespace std::ranges { […] // 25.7.23 [range.elements], elements view template<input_range V, size_t N> requires see below class elements_view; template<class T, size_t N> inline constexpr bool enable_borrowed_range<elements_view<T, N>> = enable_borrowed_range<T>; 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>; […] }Modify 25.7.23.1 [range.elements.overview] as indicated:
-3-
[Example 2:keys_view
is an alias forelements_view<
, and is useful for extracting keys from associative containers.views::all_t<R>, 0>auto names = keys_view{views::all(historical_figures)}; for (auto&& name : names) { cout << name << ' '; // prints Babbage Hamilton Lovelace Turing }— end example]
-4-values_view
is an alias forelements_view<
, and is useful for extracting values from associative containers. [Example 3:views::all_t<R>, 1>auto is_even = [](const auto x) { return x % 2 == 0; }; cout << ranges::count_if(values_view{views::all(historical_figures)}, is_even); // prints 2— end example]
[2021-06-18 Tim syncs wording to latest working draft]
The examples have been editorially corrected, so the new wording simply changes the
definition of keys_view
and values_view
.
[2021-09-20; Reflector poll]
Set status to Tentatively Ready after six votes in favour during reflector poll.
[2021-10-14 Approved at October 2021 virtual plenary. Status changed: Voting → WP.]
Proposed resolution:
This wording is relative to N4892.
Modify 25.2 [ranges.syn], header <ranges>
synopsis, as indicated:
[…] namespace std::ranges { […] // 25.7.23 [range.elements], elements view template<input_range V, size_t N> requires see below class elements_view; template<class T, size_t N> inline constexpr bool enable_borrowed_range<elements_view<T, N>> = enable_borrowed_range<T>; 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>; […] }
Modify 25.7.23.1 [range.elements.overview] as indicated:
-3-
[Example 2: … — end example] -4-keys_view
is an alias forelements_view<
, and is useful for extracting keys from associative containers.views::all_t<R>, 0>values_view
is an alias forelements_view<
, and is useful for extracting values from associative containers. [Example 3: … — end example]views::all_t<R>, 1>