Created on 2024-07-02.00:00:00 last changed 1 month ago
Proposed resolution:
This wording is relative to N4981.
Modify [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 { […] static constexpr decltype(auto) get-element(const iterator_t<Base>& i);// exposition only noexcept(noexcept(std::get<N>(*i))) requires is_reference_v<range_reference_t<Base>> { return std::get<N>(*i); } static constexpr decltype(auto) get-element(const iterator_t<Base>& i) // exposition only noexcept(noexcept(std::get<N>(*i)) && is_nothrow_move_constructible_v<tuple_element_t<N, range_reference_t<Base>>>) { using E = remove_cv_t<tuple_element_t<N, range_reference_t<Base>>>; return static_cast<E>(std::get<N>(*i)); } public: […] constexpr decltype(auto) operator*() const noexcept(noexcept(get-element(current_))) { return get-element(current_); } […] }; }
[…]
static constexpr decltype(auto) get-element(const iterator_t<Base>& i);
-3- Effects: Equivalent to:
if constexpr (is_reference_v<range_reference_t<Base>>) { return std::get<N>(*i); } else { using E = remove_cv_t<tuple_element_t<N, range_reference_t<Base>>>; return static_cast<E>(std::get<N>(*i)); }
[ 2024-08-02; Reflector poll ]
Set priority to 3 after reflector poll.
views::elements, which can be seen as a specialization of views::transform, is used to transform the original tuple into its elements.
Since neither has a specialization for iter_move, the customization point is dispatched to the default implementation. However, unlike the latter, elements_view::iterator::operator* does not have a noexcept specification, which makes calls to iter_move never noexcept, which seems to be an oversight (demo):#include <ranges> #include <vector> std::vector v{std::pair{1, "a"}, {2, "b"}}; auto r1 = v | std::views::keys; auto i1 = r1.begin(); static_assert(noexcept(*i1)); // failed static_assert(noexcept(std::ranges::iter_move(i1))); // failed auto get_key = [](auto& t) noexcept -> auto& { return std::get<0>(t); }; auto r2 = v | std::views::transform(get_key); auto i2 = r2.begin(); static_assert(noexcept(*i2)); static_assert(noexcept(std::ranges::iter_move(i2)));
The proposed resolution is aligned with the strengthened implementation of MSVC-STL.
History | |||
---|---|---|---|
Date | User | Action | Args |
2024-08-02 21:52:03 | admin | set | messages: + msg14292 |
2024-07-07 12:34:12 | admin | set | messages: + msg14229 |
2024-07-02 00:00:00 | admin | create |