From: Patrick Palka <ppalka@redhat.com>
To: gcc-patches@gcc.gnu.org
Cc: libstdc++@gcc.gnu.org, Patrick Palka <ppalka@redhat.com>
Subject: [PATCH 1/3] libstdc++: Fix elements_view::operator* and operator[] [LWG 3502]
Date: Mon, 29 Mar 2021 14:49:13 -0400 [thread overview]
Message-ID: <20210329184915.3921422-1-ppalka@redhat.com> (raw)
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.
---
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 978578197dc..cfcbcaba065 100644
--- a/libstdc++-v3/include/std/ranges
+++ b/libstdc++-v3/include/std/ranges
@@ -3234,6 +3234,10 @@ namespace views::__adaptor
{ 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>
@@ -3241,6 +3245,7 @@ namespace views::__adaptor
&& __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:
@@ -3298,10 +3303,23 @@ namespace views::__adaptor
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:
@@ -3334,8 +3352,8 @@ namespace views::__adaptor
{ 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++()
@@ -3345,7 +3363,7 @@ namespace views::__adaptor
}
constexpr void
- operator++(int) requires (!forward_range<_Base>)
+ operator++(int)
{ ++_M_current; }
constexpr _Iterator
@@ -3390,7 +3408,7 @@ namespace views::__adaptor
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 b0d122f8db5..134afd6a873 100644
--- a/libstdc++-v3/testsuite/std/ranges/adaptors/elements.cc
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/elements.cc
@@ -100,6 +100,21 @@ test04()
static_assert(!requires { 0 | elements; });
}
+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()
{
@@ -107,4 +122,5 @@ main()
test02();
test03();
test04();
+ test05();
}
--
2.31.1.133.g84d06cdc06
next reply other threads:[~2021-03-29 18:49 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-03-29 18:49 Patrick Palka [this message]
2021-03-29 18:49 ` [PATCH 2/3] libstdc++: Simplify copy-pasted algorithms in <ranges> Patrick Palka
2021-03-29 18:53 ` Patrick Palka
2021-04-01 14:07 ` Jonathan Wakely
2021-03-29 18:49 ` [PATCH 3/3] libstdc++: Fix split_view::_OuterIter::operator++ [LWG 3505] Patrick Palka
2021-04-01 14:03 ` Jonathan Wakely
2021-04-01 14:00 ` [PATCH 1/3] libstdc++: Fix elements_view::operator* and operator[] [LWG 3502] Jonathan Wakely
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210329184915.3921422-1-ppalka@redhat.com \
--to=ppalka@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=libstdc++@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).