[gcc/devel/c++-coroutines] libstdc++: Add [range.istream]
Iain D Sandoe
iains@gcc.gnu.org
Fri Feb 7 20:27:00 GMT 2020
https://gcc.gnu.org/g:b7903d9f5beb5db440e56fa057d32c6f13f7c5ec
commit b7903d9f5beb5db440e56fa057d32c6f13f7c5ec
Author: Patrick Palka <ppalka@redhat.com>
Date: Thu Feb 6 19:24:03 2020 -0500
libstdc++: Add [range.istream]
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.
Diff:
---
libstdc++-v3/ChangeLog | 4 +
libstdc++-v3/include/std/ranges | 94 +++++++++++++++++++++++
libstdc++-v3/testsuite/std/ranges/istream_view.cc | 77 +++++++++++++++++++
3 files changed, 175 insertions(+)
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index b374eff..4e01001 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,5 +1,9 @@
2020-02-07 Patrick Palka <ppalka@redhat.com>
+ * include/std/ranges (ranges::__detail::__stream_extractable,
+ ranges::basic_istream_view, ranges::istream_view): Define.
+ * testsuite/std/ranges/istream_view: New test.
+
Implement C++20 range adaptors
* include/std/ranges: Include <bits/refwrap.h> and <tuple>.
(subrange::_S_store_size): Mark as const instead of constexpr to
diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index 9f4fa34..dd0c5cf 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._M_at_end(); }
+
+ private:
+ basic_istream_view* _M_parent = nullptr;
+
+ bool
+ _M_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 0000000..1729459
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/ranges/istream_view.cc
@@ -0,0 +1,77 @@
+// 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>
+#include <testsuite_rvalref.h>
+
+namespace ranges = std::ranges;
+namespace views = std::views;
+
+struct X : __gnu_test::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);
+ VERIFY( ranges::equal(v, s, {}, &X::c) );
+}
+
+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();
+}
More information about the Libstdc++-cvs
mailing list