Title
keys_view example is broken
Status
c++23
Section
[range.elements.overview]
Submitter
Barry Revzin

Created on 2021-05-29.00:00:00 last changed 12 months ago

Messages

Date: 2021-10-14.09:56:08

Proposed resolution:

This wording is relative to N4892.

  1. Modify [ranges.syn], header <ranges> synopsis, as indicated:

    […]
    namespace std::ranges {
    […]
    
      // [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>;
    
    […]
    }
    
  2. Modify [range.elements.overview] as indicated:

    -3- keys_view is an alias for elements_view<views::all_t<R>, 0>, and is useful for extracting keys from associative containers.

    [Example 2: … — end example]

    -4- values_view is an alias for elements_view<views::all_t<R>, 1>, and is useful for extracting values from associative containers.

    [Example 3: … — end example]

Date: 2021-10-14.00:00:00

[ 2021-10-14 Approved at October 2021 virtual plenary. Status changed: Voting → WP. ]

Date: 2021-09-15.00:00:00

[ 2021-09-20; Reflector poll ]

Set status to Tentatively Ready after six votes in favour during reflector poll.

Date: 2021-06-18.00:00:00

[ 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.

Date: 2021-06-15.00:00:00

[ 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.

  1. Modify [ranges.syn], header <ranges> synopsis, as indicated:

    […]
    namespace std::ranges {
    […]
    
      // [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>;
    
    […]
    }
    
  2. Modify [range.elements.overview] as indicated:

    -3- keys_view is an alias for elements_view<views::all_t<R>, 0>, and is useful for extracting keys from associative containers.

    [Example 2:

    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 for elements_view<views::all_t<R>, 1>, and is useful for extracting values from associative containers.

    [Example 3:

    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]

Date: 2021-05-29.00:00:00

[ 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 [over.match.class.deduct] p2.3.

The proposed resolution below removes the 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.

Date: 2021-05-29.00:00:00

In [range.elements.overview] we have:

keys_view is an alias for elements_view<views::all_t<R>, 0>, and is useful for extracting keys from associative containers.

[Example 2:

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.

But class template argument deduction cannot work here, 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).

History
Date User Action Args
2023-11-22 15:47:43adminsetstatus: wp -> c++23
2021-10-14 09:56:08adminsetmessages: + msg12128
2021-10-14 09:56:08adminsetstatus: voting -> wp
2021-09-29 12:57:28adminsetstatus: ready -> voting
2021-09-20 11:34:46adminsetmessages: + msg12058
2021-09-20 11:34:46adminsetstatus: new -> ready
2021-06-19 18:11:13adminsetmessages: + msg11943
2021-06-14 14:09:34adminsetmessages: + msg11931
2021-06-06 14:35:24adminsetmessages: + msg11875
2021-06-06 14:35:24adminsetmessages: + msg11874
2021-05-29 00:00:00admincreate