* [PATCH 4/3] Add [range.istream]
@ 2020-02-07 0:53 Patrick Palka
2020-02-07 12:14 ` Jonathan Wakely
0 siblings, 1 reply; 4+ messages in thread
From: Patrick Palka @ 2020-02-07 0:53 UTC (permalink / raw)
To: gcc-patches; +Cc: libstdc++, jwakely, Patrick Palka
This patch adds ranges::basic_istream_view and ranges::istream_view. This seems
to be the last missing part of the ranges header.
libstdc++-v3/ChangeLog:
* include/std/ranges (ranges::__detail::__stream_extractable,
ranges::basic_istream_view, ranges::istream_view): Define.
* testsuite/std/ranges/istream_view: New test.
---
libstdc++-v3/include/std/ranges | 94 +++++++++++++++++++
.../testsuite/std/ranges/istream_view.cc | 76 +++++++++++++++
2 files changed, 170 insertions(+)
create mode 100644 libstdc++-v3/testsuite/std/ranges/istream_view.cc
diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index 8a8fefb6f19..88b98310ef9 100644
--- a/libstdc++-v3/include/std/ranges
+++ b/libstdc++-v3/include/std/ranges
@@ -951,6 +951,100 @@ namespace views
inline constexpr _Iota iota{};
} // namespace views
+ namespace __detail
+ {
+ template<typename _Val, typename _CharT, typename _Traits>
+ concept __stream_extractable
+ = requires(basic_istream<_CharT, _Traits>& is, _Val& t) { is >> t; };
+ } // namespace __detail
+
+ template<movable _Val, typename _CharT, typename _Traits>
+ requires default_initializable<_Val>
+ && __detail::__stream_extractable<_Val, _CharT, _Traits>
+ class basic_istream_view
+ : public view_interface<basic_istream_view<_Val, _CharT, _Traits>>
+ {
+ public:
+ basic_istream_view() = default;
+
+ constexpr explicit
+ basic_istream_view(basic_istream<_CharT, _Traits>& __stream)
+ : _M_stream(std::__addressof(__stream))
+ { }
+
+ constexpr auto
+ begin()
+ {
+ if (_M_stream != nullptr)
+ *_M_stream >> _M_object;
+ return _Iterator{*this};
+ }
+
+ constexpr default_sentinel_t
+ end() const noexcept
+ { return default_sentinel; }
+
+ private:
+ basic_istream<_CharT, _Traits>* _M_stream = nullptr;
+ _Val _M_object = _Val();
+
+ struct _Iterator
+ {
+ public:
+ using iterator_category = input_iterator_tag;
+ using difference_type = ptrdiff_t;
+ using value_type = _Val;
+
+ _Iterator() = default;
+
+ constexpr explicit
+ _Iterator(basic_istream_view& __parent) noexcept
+ : _M_parent(std::__addressof(__parent))
+ { }
+
+ _Iterator(const _Iterator&) = delete;
+ _Iterator(_Iterator&&) = default;
+ _Iterator& operator=(const _Iterator&) = delete;
+ _Iterator& operator=(_Iterator&&) = default;
+
+ _Iterator&
+ operator++()
+ {
+ __glibcxx_assert(_M_parent->_M_stream != nullptr);
+ *_M_parent->_M_stream >> _M_parent->_M_object;
+ }
+
+ void
+ operator++(int)
+ { ++*this; }
+
+ _Val&
+ operator*() const
+ {
+ __glibcxx_assert(_M_parent->_M_stream != nullptr);
+ return _M_parent->_M_object;
+ }
+
+ friend bool
+ operator==(const _Iterator& __x, default_sentinel_t)
+ { return __x.__at_end(); }
+
+ private:
+ basic_istream_view* _M_parent = nullptr;
+
+ bool
+ __at_end() const
+ { return _M_parent == nullptr || !*_M_parent->_M_stream; }
+ };
+
+ friend _Iterator;
+ };
+
+ template<typename _Val, typename _CharT, typename _Traits>
+ basic_istream_view<_Val, _CharT, _Traits>
+ istream_view(basic_istream<_CharT, _Traits>& __s)
+ { return basic_istream_view<_Val, _CharT, _Traits>{__s}; }
+
namespace __detail
{
struct _Empty { };
diff --git a/libstdc++-v3/testsuite/std/ranges/istream_view.cc b/libstdc++-v3/testsuite/std/ranges/istream_view.cc
new file mode 100644
index 00000000000..c573ba57ae8
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/ranges/istream_view.cc
@@ -0,0 +1,76 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <algorithm>
+#include <ranges>
+#include <sstream>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+namespace ranges = std::ranges;
+namespace views = std::views;
+
+struct X : __gnutest::rvalstruct
+{
+ char c;
+
+ friend std::istream&
+ operator>>(std::istream& is, X& m)
+ {
+ is >> m.c;
+ return is;
+ }
+};
+
+
+void
+test01()
+{
+ std::string s = "0123456789";
+ auto ss = std::istringstream{s};
+ auto v = ranges::istream_view<X>(ss) | views::transform(&X::c);
+ VERIFY( ranges::equal(v, s) );
+}
+
+void
+test02()
+{
+ auto ints = std::istringstream{"0 1 2 3 4"};
+ int x[5];
+ ranges::copy(ranges::istream_view<int>(ints), x);
+ VERIFY( ranges::equal(x, (int[]){0,1,2,3,4}) );
+}
+
+void
+test03()
+{
+ auto input = std::istringstream{"0 1 2 3 4 5 6 7 8 9"};
+ auto small = [](const auto x) noexcept { return x < 5; };
+ auto v = ranges::istream_view<int>(input) | views::take_while(small);
+ VERIFY( ranges::equal(v, (int[]){0,1,2,3,4}) );
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ test03();
+}
--
2.25.0.191.gde93cc14ab
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 4/3] Add [range.istream]
2020-02-07 0:53 [PATCH 4/3] Add [range.istream] Patrick Palka
@ 2020-02-07 12:14 ` Jonathan Wakely
2020-02-07 14:46 ` Patrick Palka
0 siblings, 1 reply; 4+ messages in thread
From: Jonathan Wakely @ 2020-02-07 12:14 UTC (permalink / raw)
To: Patrick Palka; +Cc: gcc-patches, libstdc++
On 06/02/20 19:52 -0500, Patrick Palka wrote:
>This patch adds ranges::basic_istream_view and ranges::istream_view. This seems
>to be the last missing part of the ranges header.
>
>libstdc++-v3/ChangeLog:
>
> * include/std/ranges (ranges::__detail::__stream_extractable,
> ranges::basic_istream_view, ranges::istream_view): Define.
> * testsuite/std/ranges/istream_view: New test.
>---
> libstdc++-v3/include/std/ranges | 94 +++++++++++++++++++
> .../testsuite/std/ranges/istream_view.cc | 76 +++++++++++++++
> 2 files changed, 170 insertions(+)
> create mode 100644 libstdc++-v3/testsuite/std/ranges/istream_view.cc
>
>diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
>index 8a8fefb6f19..88b98310ef9 100644
>--- a/libstdc++-v3/include/std/ranges
>+++ b/libstdc++-v3/include/std/ranges
>@@ -951,6 +951,100 @@ namespace views
> inline constexpr _Iota iota{};
> } // namespace views
>
>+ namespace __detail
>+ {
>+ template<typename _Val, typename _CharT, typename _Traits>
>+ concept __stream_extractable
>+ = requires(basic_istream<_CharT, _Traits>& is, _Val& t) { is >> t; };
I was going to ask for "is" and "t" to use reserved names, but those
names are actually reserved. std::ctype::is is present since C++98 and
std::binomial_distribution::t() since C++11. So the names are OK.
>+ } // namespace __detail
>+
>+ template<movable _Val, typename _CharT, typename _Traits>
>+ requires default_initializable<_Val>
>+ && __detail::__stream_extractable<_Val, _CharT, _Traits>
>+ class basic_istream_view
>+ : public view_interface<basic_istream_view<_Val, _CharT, _Traits>>
>+ {
>+ public:
>+ basic_istream_view() = default;
>+
>+ constexpr explicit
>+ basic_istream_view(basic_istream<_CharT, _Traits>& __stream)
>+ : _M_stream(std::__addressof(__stream))
>+ { }
>+
>+ constexpr auto
>+ begin()
>+ {
>+ if (_M_stream != nullptr)
>+ *_M_stream >> _M_object;
>+ return _Iterator{*this};
>+ }
>+
>+ constexpr default_sentinel_t
>+ end() const noexcept
>+ { return default_sentinel; }
>+
>+ private:
>+ basic_istream<_CharT, _Traits>* _M_stream = nullptr;
>+ _Val _M_object = _Val();
>+
>+ struct _Iterator
>+ {
>+ public:
>+ using iterator_category = input_iterator_tag;
>+ using difference_type = ptrdiff_t;
>+ using value_type = _Val;
>+
>+ _Iterator() = default;
>+
>+ constexpr explicit
>+ _Iterator(basic_istream_view& __parent) noexcept
>+ : _M_parent(std::__addressof(__parent))
>+ { }
>+
>+ _Iterator(const _Iterator&) = delete;
>+ _Iterator(_Iterator&&) = default;
>+ _Iterator& operator=(const _Iterator&) = delete;
>+ _Iterator& operator=(_Iterator&&) = default;
>+
>+ _Iterator&
>+ operator++()
>+ {
>+ __glibcxx_assert(_M_parent->_M_stream != nullptr);
>+ *_M_parent->_M_stream >> _M_parent->_M_object;
>+ }
>+
>+ void
>+ operator++(int)
>+ { ++*this; }
>+
>+ _Val&
>+ operator*() const
>+ {
>+ __glibcxx_assert(_M_parent->_M_stream != nullptr);
>+ return _M_parent->_M_object;
>+ }
>+
>+ friend bool
>+ operator==(const _Iterator& __x, default_sentinel_t)
>+ { return __x.__at_end(); }
>+
>+ private:
>+ basic_istream_view* _M_parent = nullptr;
>+
>+ bool
>+ __at_end() const
Please rename this to _M_at_end for consistency with the rest of the
library.
OK for master with that tweak, thanks.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 4/3] Add [range.istream]
2020-02-07 12:14 ` Jonathan Wakely
@ 2020-02-07 14:46 ` Patrick Palka
2020-02-07 16:18 ` Jonathan Wakely
0 siblings, 1 reply; 4+ messages in thread
From: Patrick Palka @ 2020-02-07 14:46 UTC (permalink / raw)
To: Jonathan Wakely; +Cc: Patrick Palka, gcc-patches, libstdc++
On Fri, 7 Feb 2020, Jonathan Wakely wrote:
> On 06/02/20 19:52 -0500, Patrick Palka wrote:
> > This patch adds ranges::basic_istream_view and ranges::istream_view. This
> > seems
> > to be the last missing part of the ranges header.
> >
> > libstdc++-v3/ChangeLog:
> >
> > * include/std/ranges (ranges::__detail::__stream_extractable,
> > ranges::basic_istream_view, ranges::istream_view): Define.
> > * testsuite/std/ranges/istream_view: New test.
> > ---
> > libstdc++-v3/include/std/ranges | 94 +++++++++++++++++++
> > .../testsuite/std/ranges/istream_view.cc | 76 +++++++++++++++
> > 2 files changed, 170 insertions(+)
> > create mode 100644 libstdc++-v3/testsuite/std/ranges/istream_view.cc
> >
> > diff --git a/libstdc++-v3/include/std/ranges
> > b/libstdc++-v3/include/std/ranges
> > index 8a8fefb6f19..88b98310ef9 100644
> > --- a/libstdc++-v3/include/std/ranges
> > +++ b/libstdc++-v3/include/std/ranges
> > @@ -951,6 +951,100 @@ namespace views
> > inline constexpr _Iota iota{};
> > } // namespace views
> >
> > + namespace __detail
> > + {
> > + template<typename _Val, typename _CharT, typename _Traits>
> > + concept __stream_extractable
> > + = requires(basic_istream<_CharT, _Traits>& is, _Val& t) { is >> t; };
>
> I was going to ask for "is" and "t" to use reserved names, but those
> names are actually reserved. std::ctype::is is present since C++98 and
> std::binomial_distribution::t() since C++11. So the names are OK.
Phew! :) I just forgot to uglify those names.
>
> > + } // namespace __detail
> > +
> > + template<movable _Val, typename _CharT, typename _Traits>
> > + requires default_initializable<_Val>
> > + && __detail::__stream_extractable<_Val, _CharT, _Traits>
> > + class basic_istream_view
> > + : public view_interface<basic_istream_view<_Val, _CharT, _Traits>>
> > + {
> > + public:
> > + basic_istream_view() = default;
> > +
> > + constexpr explicit
> > + basic_istream_view(basic_istream<_CharT, _Traits>& __stream)
> > + : _M_stream(std::__addressof(__stream))
> > + { }
> > +
> > + constexpr auto
> > + begin()
> > + {
> > + if (_M_stream != nullptr)
> > + *_M_stream >> _M_object;
> > + return _Iterator{*this};
> > + }
> > +
> > + constexpr default_sentinel_t
> > + end() const noexcept
> > + { return default_sentinel; }
> > +
> > + private:
> > + basic_istream<_CharT, _Traits>* _M_stream = nullptr;
> > + _Val _M_object = _Val();
> > +
> > + struct _Iterator
> > + {
> > + public:
> > + using iterator_category = input_iterator_tag;
> > + using difference_type = ptrdiff_t;
> > + using value_type = _Val;
> > +
> > + _Iterator() = default;
> > +
> > + constexpr explicit
> > + _Iterator(basic_istream_view& __parent) noexcept
> > + : _M_parent(std::__addressof(__parent))
> > + { }
> > +
> > + _Iterator(const _Iterator&) = delete;
> > + _Iterator(_Iterator&&) = default;
> > + _Iterator& operator=(const _Iterator&) = delete;
> > + _Iterator& operator=(_Iterator&&) = default;
> > +
> > + _Iterator&
> > + operator++()
> > + {
> > + __glibcxx_assert(_M_parent->_M_stream != nullptr);
> > + *_M_parent->_M_stream >> _M_parent->_M_object;
> > + }
> > +
> > + void
> > + operator++(int)
> > + { ++*this; }
> > +
> > + _Val&
> > + operator*() const
> > + {
> > + __glibcxx_assert(_M_parent->_M_stream != nullptr);
> > + return _M_parent->_M_object;
> > + }
> > +
> > + friend bool
> > + operator==(const _Iterator& __x, default_sentinel_t)
> > + { return __x.__at_end(); }
> > +
> > + private:
> > + basic_istream_view* _M_parent = nullptr;
> > +
> > + bool
> > + __at_end() const
>
> Please rename this to _M_at_end for consistency with the rest of the
> library.
>
> OK for master with that tweak, thanks.
Fixed and committed with that change. Thanks for the review!
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 4/3] Add [range.istream]
2020-02-07 14:46 ` Patrick Palka
@ 2020-02-07 16:18 ` Jonathan Wakely
0 siblings, 0 replies; 4+ messages in thread
From: Jonathan Wakely @ 2020-02-07 16:18 UTC (permalink / raw)
To: Patrick Palka; +Cc: gcc-patches, libstdc++
[-- Attachment #1: Type: text/plain, Size: 154 bytes --]
On 07/02/20 09:46 -0500, Patrick Palka wrote:
>Fixed and committed with that change. Thanks for the review!
I've just tested and pushed this fix.
[-- Attachment #2: patch.txt --]
[-- Type: text/x-patch, Size: 1079 bytes --]
commit 572992c8920d5339a3ac28d442c436d6daa0bfae
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Fri Feb 7 16:06:43 2020 +0000
libstdc++ Fix missing return in istream_view iterator
* include/std/ranges (iota_view): Add braces to prevent -Wempty-body
warning.
(basic_istream_view::_Iterator::operator++()): Add missing return.
diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index dd0c5cf6aa7..891ecf75eff 100644
--- a/libstdc++-v3/include/std/ranges
+++ b/libstdc++-v3/include/std/ranges
@@ -872,7 +872,9 @@ namespace ranges
: _M_value(__value), _M_bound(__bound)
{
if constexpr (totally_ordered_with<_Winc, _Bound>)
- __glibcxx_assert( bool(__value <= __bound) );
+ {
+ __glibcxx_assert( bool(__value <= __bound) );
+ }
}
constexpr _Iterator
@@ -1012,6 +1014,7 @@ namespace views
{
__glibcxx_assert(_M_parent->_M_stream != nullptr);
*_M_parent->_M_stream >> _M_parent->_M_object;
+ return *this;
}
void
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2020-02-07 16:18 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-07 0:53 [PATCH 4/3] Add [range.istream] Patrick Palka
2020-02-07 12:14 ` Jonathan Wakely
2020-02-07 14:46 ` Patrick Palka
2020-02-07 16:18 ` Jonathan Wakely
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).