Skip to content

Commit 53bdf14

Browse files
frederick-vs-jacopybara-github
authored andcommitted
[libc++] Fix the handling of views::take for iota_view (#75683)
Currently, when libc++'s views::take specially handles an iota_view, the addition is done after dereferencing the beginning iterator. However, in [range.take.overview]/2.3, the addition is done before the dereferencing, which means that the standard requires the returned iota_view to have the same W and Bound type in such cases. This patch fixes that, and also fixes a test that was testing the incorrect behavior. Fixes #75611 NOKEYCHECK=True GitOrigin-RevId: 1821bc1e969bd2d0887fe115ae371506adc1a8be
1 parent b872513 commit 53bdf14

File tree

2 files changed

+23
-16
lines changed

2 files changed

+23
-16
lines changed

include/__ranges/take_view.h

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -276,23 +276,31 @@ struct __fn {
276276
}
277277

278278
// [range.take.overview]: the `iota_view` case.
279+
// clang-format off
279280
template <class _Range,
280281
convertible_to<range_difference_t<_Range>> _Np,
281282
class _RawRange = remove_cvref_t<_Range>,
282283
class _Dist = range_difference_t<_Range>>
283-
requires(!__is_empty_view<_RawRange> && random_access_range<_RawRange> && sized_range<_RawRange> &&
284-
__is_iota_specialization<_RawRange>)
285-
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto
286-
operator()(_Range&& __rng, _Np&& __n) const noexcept(noexcept(ranges::iota_view(
287-
*ranges::begin(__rng), *ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n)))))
288-
-> decltype(ranges::iota_view(
289-
// Note: deliberately not forwarding `__rng` to guard against double moves.
290-
*ranges::begin(__rng),
291-
*ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n)))) {
292-
return ranges::iota_view(*ranges::begin(__rng),
293-
*ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n)));
294-
}
295-
// clang-format off
284+
requires (!__is_empty_view<_RawRange> &&
285+
random_access_range<_RawRange> &&
286+
sized_range<_RawRange> &&
287+
__is_iota_specialization<_RawRange>)
288+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI
289+
constexpr auto operator()(_Range&& __rng, _Np&& __n) const
290+
noexcept(noexcept(ranges::iota_view(
291+
*ranges::begin(__rng),
292+
*(ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n)))
293+
)))
294+
-> decltype( ranges::iota_view(
295+
// Note: deliberately not forwarding `__rng` to guard against double moves.
296+
*ranges::begin(__rng),
297+
*(ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n)))
298+
))
299+
{ return ranges::iota_view(
300+
*ranges::begin(__rng),
301+
*(ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n)))
302+
); }
303+
296304
#if _LIBCPP_STD_VER >= 23
297305
// [range.take.overview]: the `repeat_view` "_RawRange models sized_range" case.
298306
template <class _Range,

test/std/ranges/range.adaptors/range.take/adaptor.pass.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,8 @@ constexpr bool test() {
172172
// `views::take(iota_view, n)` returns an `iota_view`.
173173
{
174174
auto iota = std::views::iota(1, 8);
175-
// The second template argument of the resulting `iota_view` is different because it has to be able to hold
176-
// the `range_difference_t` of the input `iota_view`.
177-
using Result = std::ranges::iota_view<int, std::ranges::range_difference_t<decltype(iota)>>;
175+
// The second template argument of the resulting `iota_view` is same as the first.
176+
using Result = std::ranges::iota_view<int, int>;
178177
std::same_as<Result> decltype(auto) result = iota | std::views::take(3);
179178
assert(result.size() == 3);
180179
}

0 commit comments

Comments
 (0)