mirror of
https://github.com/gcc-mirror/gcc.git
synced 2026-05-06 14:59:39 +02:00
libstdc++: Make ranges::distance work with volatile iterators (LWG 4242)
This implements LWG 4242 which was approved in Sofia 2025. I don't think the change from static_cast<const decay_t<I>&> to just static_cast<decay_t<I>> is observable, but it doesn't hurt. What fixes the problem identified in the issue is the is_array_v check, which avoids the static_cast entirely for volatile-qualified iterators. libstdc++-v3/ChangeLog: * include/bits/ranges_base.h (distance(It&&, Sent)): Only decay arrays to pointers when the type is actually an array, as per LWG 4242. * testsuite/24_iterators/range_operations/distance.cc: Add test for LWG 4242. Reviewed-by: Tomasz Kamiński <tkaminsk@redhat.com>
This commit is contained in:
committed by
Jonathan Wakely
parent
a65cafbc52
commit
c351a240ad
@@ -969,8 +969,6 @@ namespace ranges
|
||||
|
||||
struct __distance_fn final
|
||||
{
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 3664. LWG 3392 broke std::ranges::distance(a, a+3)
|
||||
template<typename _It, sentinel_for<_It> _Sent>
|
||||
requires (!sized_sentinel_for<_Sent, _It>)
|
||||
constexpr iter_difference_t<_It>
|
||||
@@ -985,11 +983,20 @@ namespace ranges
|
||||
return __n;
|
||||
}
|
||||
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 3392. cannot be used on a move-only iterator with a sized sentinel
|
||||
// 3664. LWG 3392 broke std::ranges::distance(a, a+3)
|
||||
// 4242. ranges::distance does not work with volatile iterators
|
||||
template<typename _It, sized_sentinel_for<decay_t<_It>> _Sent>
|
||||
[[nodiscard, __gnu__::__always_inline__]]
|
||||
constexpr iter_difference_t<decay_t<_It>>
|
||||
operator()(_It&& __first, _Sent __last) const
|
||||
{ return __last - static_cast<const decay_t<_It>&>(__first); }
|
||||
{
|
||||
if constexpr (!is_array_v<remove_reference_t<_It>>)
|
||||
return __last - __first;
|
||||
else
|
||||
return __last - static_cast<decay_t<_It>>(__first);
|
||||
}
|
||||
|
||||
template<range _Range>
|
||||
[[nodiscard, __gnu__::__always_inline__]]
|
||||
|
||||
@@ -154,6 +154,23 @@ test06()
|
||||
VERIFY( std::ranges::distance(a+3, a) == -3 );
|
||||
}
|
||||
|
||||
void
|
||||
test_lwg4242()
|
||||
{
|
||||
// LWG 4242. ranges::distance does not work with volatile iterators
|
||||
int arr[] = {1, 2, 3};
|
||||
int* volatile ptr = arr;
|
||||
auto d1 = std::distance(ptr, arr + 3);
|
||||
auto d2 = std::ranges::distance(ptr, arr + 3);
|
||||
VERIFY( d1 == d2 );
|
||||
|
||||
// This is not part of LWG 4242 but it doesn't hurt to check it anyway:
|
||||
volatile int vol_arr[1]{};
|
||||
auto d3 = std::distance(vol_arr, vol_arr + 1);
|
||||
auto d4 = std::ranges::distance(vol_arr, vol_arr + 1);
|
||||
VERIFY( d3 == d4 );
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
@@ -163,4 +180,5 @@ main()
|
||||
test04();
|
||||
test05();
|
||||
test06();
|
||||
test_lwg4242();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user