Skip to content

[libc++][ranges] LWG3564: transform_view::iterator<true>::value_type and iterator_category should use const F& #91816

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 12, 2024

Conversation

xiaoyang-sde
Copy link
Member

Introduction

This patch implements LWG3564: transform_view::iterator<true>::value_type and iterator_category should use const F&.

transform_view's iterator currently obtained from a const transform_view invoke the transformation function as const, but the value_type and iterator_category determination uses non-const F&.

Reference

@xiaoyang-sde xiaoyang-sde requested a review from a team as a code owner May 10, 2024 21:46
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label May 10, 2024
@llvmbot
Copy link
Member

llvmbot commented May 10, 2024

@llvm/pr-subscribers-libcxx

Author: Xiaoyang Liu (xiaoyang-sde)

Changes

Introduction

This patch implements LWG3564: transform_view::iterator&lt;true&gt;::value_type and iterator_category should use const F&amp;.

transform_view's iterator currently obtained from a const transform_view invoke the transformation function as const, but the value_type and iterator_category determination uses non-const F&amp;.

Reference


Full diff: https://github.com/llvm/llvm-project/pull/91816.diff

4 Files Affected:

  • (modified) libcxx/docs/Status/Cxx23Issues.csv (+1-1)
  • (modified) libcxx/include/__ranges/transform_view.h (+6-6)
  • (modified) libcxx/test/std/ranges/range.adaptors/range.transform/iterator/types.pass.cpp (+15)
  • (modified) libcxx/test/std/ranges/range.adaptors/range.transform/types.h (+5)
diff --git a/libcxx/docs/Status/Cxx23Issues.csv b/libcxx/docs/Status/Cxx23Issues.csv
index 04f6e23375acd..fef60d289f86f 100644
--- a/libcxx/docs/Status/Cxx23Issues.csv
+++ b/libcxx/docs/Status/Cxx23Issues.csv
@@ -159,7 +159,7 @@
 "`3660 <https://wg21.link/LWG3660>`__","``iterator_traits<common_iterator>::pointer`` should conform to §[iterator.traits]","February 2022","|Complete|","14.0","|ranges|"
 "`3661 <https://wg21.link/LWG3661>`__","``constinit atomic<shared_ptr<T>> a(nullptr);`` should work","February 2022","",""
 "","","","","",""
-"`3564 <https://wg21.link/LWG3564>`__","``transform_view::iterator<true>::value_type`` and ``iterator_category`` should use ``const F&``","July 2022","","","|ranges|"
+"`3564 <https://wg21.link/LWG3564>`__","``transform_view::iterator<true>::value_type`` and ``iterator_category`` should use ``const F&``","July 2022","|Complete|","19.0","|ranges|"
 "`3617 <https://wg21.link/LWG3617>`__","``function``/``packaged_task`` deduction guides and deducing ``this``","July 2022","",""
 "`3656 <https://wg21.link/LWG3656>`__","Inconsistent bit operations returning a count","July 2022","|Complete|","15.0",""
 "`3659 <https://wg21.link/LWG3659>`__","Consider ``ATOMIC_FLAG_INIT`` undeprecation","July 2022","|Complete|","15.0"
diff --git a/libcxx/include/__ranges/transform_view.h b/libcxx/include/__ranges/transform_view.h
index dc3aaa59ed8c3..af973076e04f8 100644
--- a/libcxx/include/__ranges/transform_view.h
+++ b/libcxx/include/__ranges/transform_view.h
@@ -153,15 +153,15 @@ struct __transform_view_iterator_concept<_View> {
   using type = forward_iterator_tag;
 };
 
-template <class, class>
+template <class, class, bool>
 struct __transform_view_iterator_category_base {};
 
-template <forward_range _View, class _Fn>
-struct __transform_view_iterator_category_base<_View, _Fn> {
+template <forward_range _View, class _Fn, bool _Const>
+struct __transform_view_iterator_category_base<_View, _Fn, _Const> {
   using _Cat = typename iterator_traits<iterator_t<_View>>::iterator_category;
 
   using iterator_category =
-      conditional_t< is_reference_v<invoke_result_t<_Fn&, range_reference_t<_View>>>,
+      conditional_t< is_reference_v<invoke_result_t<__maybe_const<_Const, _Fn>&, range_reference_t<_View>>>,
                      conditional_t< derived_from<_Cat, contiguous_iterator_tag>, random_access_iterator_tag, _Cat >,
                      input_iterator_tag >;
 };
@@ -173,7 +173,7 @@ template <input_range _View, copy_constructible _Fn>
 #  endif
   requires __transform_view_constraints<_View, _Fn>
 template <bool _Const>
-class transform_view<_View, _Fn>::__iterator : public __transform_view_iterator_category_base<_View, _Fn> {
+class transform_view<_View, _Fn>::__iterator : public __transform_view_iterator_category_base<_View, _Fn, _Const> {
 
   using _Parent = __maybe_const<_Const, transform_view>;
   using _Base   = __maybe_const<_Const, _View>;
@@ -190,7 +190,7 @@ class transform_view<_View, _Fn>::__iterator : public __transform_view_iterator_
   iterator_t<_Base> __current_ = iterator_t<_Base>();
 
   using iterator_concept = typename __transform_view_iterator_concept<_View>::type;
-  using value_type       = remove_cvref_t<invoke_result_t<_Fn&, range_reference_t<_Base>>>;
+  using value_type       = remove_cvref_t<invoke_result_t<__maybe_const<_Const, _Fn>&, range_reference_t<_Base>>>;
   using difference_type  = range_difference_t<_Base>;
 
   _LIBCPP_HIDE_FROM_ABI __iterator()
diff --git a/libcxx/test/std/ranges/range.adaptors/range.transform/iterator/types.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.transform/iterator/types.pass.cpp
index 25d8936f4e4eb..17340467f856b 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.transform/iterator/types.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.transform/iterator/types.pass.cpp
@@ -61,6 +61,21 @@ constexpr bool test() {
     static_assert(std::same_as<typename TIter::value_type, int>);
     static_assert(std::same_as<typename TIter::difference_type, std::ptrdiff_t>);
   }
+  {
+    // Member typedefs for random access iterator, LWG3564 mutable overload
+    using TView = std::ranges::transform_view<RandomAccessView, PlusOneMutableOverload>;
+    using TIter = std::ranges::iterator_t<TView>;
+    static_assert(std::same_as<typename TIter::iterator_concept, std::random_access_iterator_tag>);
+    static_assert(std::same_as<typename TIter::iterator_category, std::random_access_iterator_tag>);
+    static_assert(std::same_as<typename TIter::value_type, int>);
+    static_assert(std::same_as<typename TIter::difference_type, std::ptrdiff_t>);
+
+    using CTIter = std::ranges::iterator_t<const TView>;
+    static_assert(std::same_as<typename CTIter::iterator_concept, std::random_access_iterator_tag>);
+    static_assert(std::same_as<typename CTIter::iterator_category, std::input_iterator_tag>); // Note: this is now input_iterator_tag.
+    static_assert(std::same_as<typename CTIter::value_type, int>);
+    static_assert(std::same_as<typename CTIter::difference_type, std::ptrdiff_t>);
+  }
   {
     // Member typedefs for bidirectional iterator.
     using TView = std::ranges::transform_view<BidirectionalView, Increment>;
diff --git a/libcxx/test/std/ranges/range.adaptors/range.transform/types.h b/libcxx/test/std/ranges/range.adaptors/range.transform/types.h
index 14f85722a8c19..9268a977b8109 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.transform/types.h
+++ b/libcxx/test/std/ranges/range.adaptors/range.transform/types.h
@@ -137,6 +137,11 @@ struct PlusOne {
   constexpr int operator()(int x) const { return x + 1; }
 };
 
+struct PlusOneMutableOverload {
+  constexpr int operator()(int x) const { return x + 1; }
+  constexpr int& operator()(int& x) { return ++x; }
+};
+
 struct Increment {
   constexpr int& operator()(int& x) { return ++x; }
 };

@xiaoyang-sde xiaoyang-sde added the ranges Issues related to `<ranges>` label May 10, 2024
Copy link

github-actions bot commented May 10, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Member

@ldionne ldionne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the patch and sorry for the review delay. Let's move this to LLVM 20, rebase to get the CI running and merge once the CI is green. LGTM.

@xiaoyang-sde
Copy link
Member Author

Thanks for the patch and sorry for the review delay. Let's move this to LLVM 20, rebase to get the CI running and merge once the CI is green. LGTM.

Feel free to merge this patch if it looks good!

@mordante
Copy link
Member

mordante commented Aug 3, 2024

Thanks for the patch and sorry for the review delay. Let's move this to LLVM 20, rebase to get the CI running and merge once the CI is green. LGTM.

Feel free to merge this patch if it looks good!

There is a new merge conflict. Can you rebase this patch?

…' and 'iterator_category' should use 'const F&'
Copy link
Member

@ldionne ldionne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be merged once CI is green.

@xiaoyang-sde
Copy link
Member Author

xiaoyang-sde commented Aug 8, 2024

This can be merged once CI is green.

Thanks for resolving the merge conflict! Could you please restart the failed tests? It seems that these are false negatives.

@mordante mordante merged commit d9caea1 into llvm:main Aug 12, 2024
59 checks passed
@mordante
Copy link
Member

This can be merged once CI is green.

Thanks for resolving the merge conflict! Could you please restart the failed tests? It seems that these are false negatives.

Done and merged. Thanks for your patch!

@xiaoyang-sde xiaoyang-sde deleted the lwg3564 branch November 10, 2024 17:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. ranges Issues related to `<ranges>`
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants