diff options
author | Patrick Palka <ppalka@redhat.com> | 2020-02-06 19:24:03 -0500 |
---|---|---|
committer | Patrick Palka <ppalka@redhat.com> | 2020-02-07 09:44:53 -0500 |
commit | b7903d9f5beb5db440e56fa057d32c6f13f7c5ec (patch) | |
tree | bc647bce465c57a8841a03230c8c28c67c60056c | |
parent | 55d4cbcba8f1c74fa90ed53059114ccaaf549ad7 (diff) | |
download | gcc-b7903d9f5beb5db440e56fa057d32c6f13f7c5ec.zip gcc-b7903d9f5beb5db440e56fa057d32c6f13f7c5ec.tar.gz gcc-b7903d9f5beb5db440e56fa057d32c6f13f7c5ec.tar.bz2 |
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.
-rw-r--r-- | libstdc++-v3/ChangeLog | 4 | ||||
-rw-r--r-- | libstdc++-v3/include/std/ranges | 94 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/std/ranges/istream_view.cc | 77 |
3 files changed, 175 insertions, 0 deletions
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(); +} |