From 510bd1c178f3719df7148dd584d30acc2595dc3c Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Mon, 24 Feb 2020 16:38:07 -0500 Subject: [PATCH] libstdc++: LWG 3301 transform_view::iterator has incorrect iterator_category libstdc++-v3/ChangeLog: LWG 3301 transform_view::_Iterator has incorrect iterator_category * include/std/ranges (transform_view::_Iterator::_S_iter_cat): Adjust determination of iterator_category as per LWG 3301. * testsuite/std/ranges/adaptors/transform.cc: Augment test. --- libstdc++-v3/ChangeLog | 5 ++++ libstdc++-v3/include/std/ranges | 16 +++++++++---- .../std/ranges/adaptors/transform.cc | 24 +++++++++++++++++++ 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 046d50de6d1..1a56a7d221c 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,10 @@ 2020-02-25 Patrick Palka + LWG 3301 transform_view::_Iterator has incorrect iterator_category + * include/std/ranges (transform_view::_Iterator::_S_iter_cat): Adjust + determination of iterator_category as per LWG 3301. + * testsuite/std/ranges/adaptors/transform.cc: Augment test. + LWG 3292 iota_view is under-constrained * include/std/ranges (iota_view): Require that _Winc models semiregular as per LWG 3292. diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index ab8fbaca38f..aed90e9710e 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -1570,12 +1570,18 @@ namespace views static constexpr auto _S_iter_cat() { - using _Cat - = typename iterator_traits<_Base_iter>::iterator_category; - if constexpr (derived_from<_Cat, contiguous_iterator_tag>) - return random_access_iterator_tag{}; + using _Res = invoke_result_t<_Fp&, range_reference_t<_Base>>; + if constexpr (is_lvalue_reference_v<_Res>) + { + using _Cat + = typename iterator_traits<_Base_iter>::iterator_category; + if constexpr (derived_from<_Cat, contiguous_iterator_tag>) + return random_access_iterator_tag{}; + else + return _Cat{}; + } else - return _Cat{}; + return input_iterator_tag{}; } static constexpr decltype(auto) diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc index ad51fffb43d..178544d6378 100644 --- a/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc @@ -77,10 +77,34 @@ test03() VERIFY( ranges::equal(v, (int[]){1,2,3,4,5}) ); } +void +test04() +{ + // LWG 3301 + { + auto f = [] (int x) { return x; }; + int x[] = {1,2,3,4,5}; + auto v = x | views::transform(f); + auto i = v.begin(); + using Cat = decltype(i)::iterator_category; + static_assert(std::same_as); + } + + { + auto f = [] (int &x) -> int& { return x; }; + int x[] = {1,2,3,4,5}; + auto v = x | views::transform(f); + auto i = v.begin(); + using Cat = decltype(i)::iterator_category; + static_assert(std::derived_from); + } +} + int main() { test01(); test02(); test03(); + test04(); } -- 2.30.2