Movatterモバイル変換


[0]ホーム

URL:



This page is a snapshot from the LWG issues list, see theLibrary Active Issues List for more information and the meaning ofC++23 status.

3502.elements_view should not be allowed to return dangling references

Section: 25.7.23.3[range.elements.iterator]Status:C++23Submitter: Tim SongOpened: 2020-11-18Last modified: 2023-11-22

Priority:2

View otheractive issues in [range.elements.iterator].

View all otherissues in [range.elements.iterator].

View all issues withC++23 status.

Discussion:

This compiles but the resulting view is full of dangling references:

std::vector<int> vec = {42};auto r = vec | std::views::transform([](auto c) { return std::make_tuple(c, c); })             | std::views::keys;

This is becauseelements_view::iterator::operator* is specified as

constexpr decltype(auto) operator*() const { return get<N>(*current_); }

Here*current_ is a prvalue, and so theget<N> produces a referenceinto the materialized temporary that becomes dangling as soon asoperator* returns.

We should either ban this case altogether, or makeoperator* (andoperator[]) return byvalue when*current_ is a prvalue and the corresponding tuple element is not a reference (since thisget isstd::get, we need not worry about weird user-defined overloads.)

[2020-11-29; Reflector prioritization]

Set priority to 2 during reflector discussions.

[2021-01-31 Tim adds PR]

[2021-02-08; Reflector poll]

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

[2021-02-26 Approved at February 2021 virtual plenary. Status changed: Tentatively Ready → WP.]

Proposed resolution:

This wording is relative toN4878.

  1. Modify 25.7.23.2[range.elements.view], as indicated:

    namespace std::ranges {  template<class T, size_t N>    concepthas-tuple-element =                   // exposition only      requires(T t) {        typename tuple_size<T>::type;        requires N < tuple_size_v<T>;        typename tuple_element_t<N, T>;        { get<N>(t) } -> convertible_to<const tuple_element_t<N, T>&>;      };  template<class T, size_t N>  conceptreturnable-element = is_reference_v<T> || move_­constructible<tuple_element_t<N, T>>;  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>> {    […]  };}
  2. Modify 25.7.23.3[range.elements.iterator] as indicated:

    namespace std::ranges {  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>  template<bool Const>  class elements_view<V, N>::iterator {                 // exposition only    usingBase =maybe-const<Const, V>;                 // exposition only    iterator_t<Base>current_ = iterator_t<Base>();     // exposition only    static constexpr decltype(auto)get-element(const iterator_t<Base>& i);    // exposition only  public:    […]    constexpr decltype(auto) operator*() const    { returnget<N>get-element(*current_); }    […]    constexpr decltype(auto) operator[](difference_type n) const    requires random_­access_­range<Base>    { returnget<N>get-element(*(current_ + n)); }  };}
    static constexpr decltype(auto)get-element(const iterator_t<Base>& i);    // exposition only

    -?-Effects: Equivalent to:

    if constexpr (is_reference_v<range_reference_t<Base>>) {  return get<N>(*i);}else {  using E = remove_cv_t<tuple_element_t<N, range_reference_t<Base>>>;  return static_cast<E>(get<N>(*i));}
  3. Modify 25.7.23.4[range.elements.sentinel] as indicated:

    namespace std::ranges {  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>  template<bool Const>  class elements_view<V, N>::sentinel {                 // exposition only    […]  };}

[8]ページ先頭

©2009-2026 Movatter.jp