diff mbox series

libstdc++: Implement LWG 3564 for ranges::transform_view

Message ID 20241013235310.1722385-1-jwakely@redhat.com
State New
Headers show
Series libstdc++: Implement LWG 3564 for ranges::transform_view | expand

Commit Message

Jonathan Wakely Oct. 13, 2024, 11:52 p.m. UTC
Tested x86_64-linux.

-- >8 --

The _Iterator<true> type returned by begin() const uses const F& to
transform the elements, so it should use const F& to determine the
iterator's value_type and iterator_category as well.

This was accepted into the WP in July 2022.

libstdc++-v3/ChangeLog:

	* include/std/ranges (transform_view:_Iterator): Use const F&
	to determine value_type and iterator_category of
	_Iterator<true>, as per LWG 3564.
	* testsuite/std/ranges/adaptors/transform.cc: Check value_type
	and iterator_category.
---
 libstdc++-v3/include/std/ranges               |  9 +++++++--
 .../std/ranges/adaptors/transform.cc          | 19 +++++++++++++++++++
 2 files changed, 26 insertions(+), 2 deletions(-)

Comments

Patrick Palka Oct. 14, 2024, 6:37 p.m. UTC | #1
On Mon, 14 Oct 2024, Jonathan Wakely wrote:

> Tested x86_64-linux.
> 
> -- >8 --
> 
> The _Iterator<true> type returned by begin() const uses const F& to
> transform the elements, so it should use const F& to determine the
> iterator's value_type and iterator_category as well.
> 
> This was accepted into the WP in July 2022.
> 
> libstdc++-v3/ChangeLog:
> 
> 	* include/std/ranges (transform_view:_Iterator): Use const F&
> 	to determine value_type and iterator_category of
> 	_Iterator<true>, as per LWG 3564.
> 	* testsuite/std/ranges/adaptors/transform.cc: Check value_type
> 	and iterator_category.
> ---
>  libstdc++-v3/include/std/ranges               |  9 +++++++--
>  .../std/ranges/adaptors/transform.cc          | 19 +++++++++++++++++++
>  2 files changed, 26 insertions(+), 2 deletions(-)
> 
> diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
> index 6e6e3b97d82..f0d81cbea0c 100644
> --- a/libstdc++-v3/include/std/ranges
> +++ b/libstdc++-v3/include/std/ranges
> @@ -1886,8 +1886,12 @@ namespace views::__adaptor
>  	  static auto
>  	  _S_iter_cat()
>  	  {
> +	    // _GLIBCXX_RESOLVE_LIB_DEFECTS
> +	    // 3564. transform_view::iterator<true>::value_type and
> +	    // iterator_category should use const F&
> +	    using _Fpc = __detail::__maybe_const_t<_Const, _Fp>;

We can use __maybe_const_t unqualified here (ever since
r13-3758-gf471cb71c86c1e).

>  	    using _Base = transform_view::_Base<_Const>;
> -	    using _Res = invoke_result_t<_Fp&, range_reference_t<_Base>>;
> +	    using _Res = invoke_result_t<_Fpc&, range_reference_t<_Base>>;
>  	    if constexpr (is_lvalue_reference_v<_Res>)
>  	      {
>  		using _Cat
> @@ -1927,6 +1931,7 @@ namespace views::__adaptor
>  	      return input_iterator_tag{};
>  	  }
>  
> +	  using _Fpc = __detail::__maybe_const_t<_Const, _Fp>;

Same here.  LGTM besides that.

>  	  using _Base_iter = iterator_t<_Base>;
>  
>  	  _Base_iter _M_current = _Base_iter();
> @@ -1936,7 +1941,7 @@ namespace views::__adaptor
>  	  using iterator_concept = decltype(_S_iter_concept());
>  	  // iterator_category defined in __transform_view_iter_cat
>  	  using value_type
> -	    = remove_cvref_t<invoke_result_t<_Fp&, range_reference_t<_Base>>>;
> +	    = remove_cvref_t<invoke_result_t<_Fpc&, range_reference_t<_Base>>>;
>  	  using difference_type = range_difference_t<_Base>;
>  
>  	  _Iterator() requires default_initializable<_Base_iter> = default;
> diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc
> index bcb18a3fc6c..ca695349650 100644
> --- a/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc
> +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc
> @@ -196,6 +196,24 @@ test09()
>  #endif
>  }
>  
> +void
> +test10()
> +{
> +  struct F {
> +    short operator()(int) { return 0; }
> +    const int& operator()(const int& i) const { return i; }
> +  };
> +
> +  int x[] {2, 4};
> +  const auto xform = x | views::transform(F{});
> +  using const_iterator = decltype(xform.begin());
> +  // LWG 3564. transform_view::iterator<true>::value_type and iterator_category
> +  // should use const F&
> +  static_assert(std::same_as<std::iter_value_t<const_iterator>, int>);
> +  using cat = std::iterator_traits<const_iterator>::iterator_category;
> +  static_assert(std::same_as<cat, std::random_access_iterator_tag>);
> +}
> +
>  int
>  main()
>  {
> @@ -208,4 +226,5 @@ main()
>    test07();
>    test08();
>    test09();
> +  test10();
>  }
> -- 
> 2.46.2
> 
>
diff mbox series

Patch

diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index 6e6e3b97d82..f0d81cbea0c 100644
--- a/libstdc++-v3/include/std/ranges
+++ b/libstdc++-v3/include/std/ranges
@@ -1886,8 +1886,12 @@  namespace views::__adaptor
 	  static auto
 	  _S_iter_cat()
 	  {
+	    // _GLIBCXX_RESOLVE_LIB_DEFECTS
+	    // 3564. transform_view::iterator<true>::value_type and
+	    // iterator_category should use const F&
+	    using _Fpc = __detail::__maybe_const_t<_Const, _Fp>;
 	    using _Base = transform_view::_Base<_Const>;
-	    using _Res = invoke_result_t<_Fp&, range_reference_t<_Base>>;
+	    using _Res = invoke_result_t<_Fpc&, range_reference_t<_Base>>;
 	    if constexpr (is_lvalue_reference_v<_Res>)
 	      {
 		using _Cat
@@ -1927,6 +1931,7 @@  namespace views::__adaptor
 	      return input_iterator_tag{};
 	  }
 
+	  using _Fpc = __detail::__maybe_const_t<_Const, _Fp>;
 	  using _Base_iter = iterator_t<_Base>;
 
 	  _Base_iter _M_current = _Base_iter();
@@ -1936,7 +1941,7 @@  namespace views::__adaptor
 	  using iterator_concept = decltype(_S_iter_concept());
 	  // iterator_category defined in __transform_view_iter_cat
 	  using value_type
-	    = remove_cvref_t<invoke_result_t<_Fp&, range_reference_t<_Base>>>;
+	    = remove_cvref_t<invoke_result_t<_Fpc&, range_reference_t<_Base>>>;
 	  using difference_type = range_difference_t<_Base>;
 
 	  _Iterator() requires default_initializable<_Base_iter> = default;
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc
index bcb18a3fc6c..ca695349650 100644
--- a/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc
@@ -196,6 +196,24 @@  test09()
 #endif
 }
 
+void
+test10()
+{
+  struct F {
+    short operator()(int) { return 0; }
+    const int& operator()(const int& i) const { return i; }
+  };
+
+  int x[] {2, 4};
+  const auto xform = x | views::transform(F{});
+  using const_iterator = decltype(xform.begin());
+  // LWG 3564. transform_view::iterator<true>::value_type and iterator_category
+  // should use const F&
+  static_assert(std::same_as<std::iter_value_t<const_iterator>, int>);
+  using cat = std::iterator_traits<const_iterator>::iterator_category;
+  static_assert(std::same_as<cat, std::random_access_iterator_tag>);
+}
+
 int
 main()
 {
@@ -208,4 +226,5 @@  main()
   test07();
   test08();
   test09();
+  test10();
 }