public inbox for libstdc++-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r10-9738] libstdc++: Fix elements_view::operator* and operator[] [LWG 3502]
@ 2021-04-21  3:27 Patrick Palka
  0 siblings, 0 replies; only message in thread
From: Patrick Palka @ 2021-04-21  3:27 UTC (permalink / raw)
  To: gcc-cvs, libstdc++-cvs

https://gcc.gnu.org/g:d1af36d4f9d80dc7081078ede2999bd4853cfb75

commit r10-9738-gd1af36d4f9d80dc7081078ede2999bd4853cfb75
Author: Patrick Palka <ppalka@redhat.com>
Date:   Thu Apr 8 16:45:22 2021 -0400

    libstdc++: Fix elements_view::operator* and operator[] [LWG 3502]
    
    While we're modifying elements_view, this also implements the one-line
    resolution of LWG 3492.
    
    libstdc++-v3/ChangeLog:
    
            * include/std/ranges (__detail::__returnable_element): New
            concept.
            (elements_view): Use this concept in its constraints.  Add
            missing private access specifier.
            (elements_view::_S_get_element): Define as per LWG 3502.
            (elements_view::operator*, elements_view::operator[]): Use
            _S_get_element.
            (elements_view::operator++): Remove unnecessary constraint
            as per LWG 3492.
            * testsuite/std/ranges/adaptors/elements.cc (test05): New test.
    
    (cherry picked from commit c7fe68f3652ceefaf297611d1e64c8d9da43ad93)

Diff:
---
 libstdc++-v3/include/std/ranges                    | 26 ++++++++++++++++++----
 .../testsuite/std/ranges/adaptors/elements.cc      | 16 +++++++++++++
 2 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index ad882042475..880f6eefc80 100644
--- a/libstdc++-v3/include/std/ranges
+++ b/libstdc++-v3/include/std/ranges
@@ -3373,6 +3373,10 @@ namespace views
 	{ std::get<_Nm>(__t) }
 	  -> convertible_to<const tuple_element_t<_Nm, _Tp>&>;
       };
+
+    template<typename _Tp, size_t _Nm>
+      concept __returnable_element
+	= is_reference_v<_Tp> || move_constructible<tuple_element_t<_Nm, _Tp>>;
   }
 
   template<input_range _Vp, size_t _Nm>
@@ -3380,6 +3384,7 @@ namespace views
       && __detail::__has_tuple_element<range_value_t<_Vp>, _Nm>
       && __detail::__has_tuple_element<remove_reference_t<range_reference_t<_Vp>>,
 				       _Nm>
+      && __detail::__returnable_element<range_reference_t<_Vp>, _Nm>
     class elements_view : public view_interface<elements_view<_Vp, _Nm>>
     {
     public:
@@ -3437,10 +3442,23 @@ namespace views
       template<bool _Const>
 	struct _Iterator
 	{
+	private:
 	  using _Base = __detail::__maybe_const_t<_Const, _Vp>;
 
 	  iterator_t<_Base> _M_current = iterator_t<_Base>();
 
+	  static constexpr decltype(auto)
+	  _S_get_element(const iterator_t<_Base>& __i)
+	  {
+	    if constexpr (is_reference_v<range_reference_t<_Base>>)
+	      return std::get<_Nm>(*__i);
+	    else
+	      {
+		using _Et = remove_cv_t<tuple_element_t<_Nm, range_reference_t<_Base>>>;
+		return static_cast<_Et>(std::get<_Nm>(*__i));
+	      }
+	  }
+
 	  friend _Iterator<!_Const>;
 
 	public:
@@ -3473,8 +3491,8 @@ namespace views
 	  { return std::move(_M_current); }
 
 	  constexpr decltype(auto)
-	    operator*() const
-	  { return std::get<_Nm>(*_M_current); }
+	  operator*() const
+	  { return _S_get_element(_M_current); }
 
 	  constexpr _Iterator&
 	  operator++()
@@ -3484,7 +3502,7 @@ namespace views
 	  }
 
 	  constexpr void
-	  operator++(int) requires (!forward_range<_Base>)
+	  operator++(int)
 	  { ++_M_current; }
 
 	  constexpr _Iterator
@@ -3529,7 +3547,7 @@ namespace views
 	  constexpr decltype(auto)
 	  operator[](difference_type __n) const
 	    requires random_access_range<_Base>
-	  { return std::get<_Nm>(*(_M_current + __n)); }
+	  { return _S_get_element(_M_current + __n); }
 
 	  friend constexpr bool
 	  operator==(const _Iterator& __x, const _Iterator& __y)
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/elements.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/elements.cc
index 94dd7c94505..2e15250d31e 100644
--- a/libstdc++-v3/testsuite/std/ranges/adaptors/elements.cc
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/elements.cc
@@ -89,10 +89,26 @@ test03()
   VERIFY( (next(b_const, 2) - b_const) == 2 );
 }
 
+void
+test05()
+{
+  // LWG 3502
+  std::vector<int> vec = {42};
+  auto r1 = vec
+    | views::transform([](auto c) { return std::make_tuple(c, c); })
+    | views::keys;
+  VERIFY( ranges::equal(r1, (int[]){42}) );
+
+  std::tuple<int, int> a[] = {{1,2},{3,4}};
+  auto r2 = a | views::keys;
+  VERIFY( r2[0] == 1 && r2[1] == 3 );
+}
+
 int
 main()
 {
   test01();
   test02();
   test03();
+  test05();
 }


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-04-21  3:27 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-21  3:27 [gcc r10-9738] libstdc++: Fix elements_view::operator* and operator[] [LWG 3502] Patrick Palka

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).