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.

Reply via email to