From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2136) id 1AD903939C38; Wed, 17 Jun 2020 18:42:29 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 1AD903939C38 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1592419349; bh=RP6D9fqNZ74csFMLvkqEJSnh4ujwogTnGt0PR0X4+aM=; h=From:To:Subject:Date:From; b=M76GMVGMNxS04j6u0MM2OLcNv4/nx+KSrAZOiK9iWdEQoJQE4wRPB1Nl40Ib2sx+P A9SxFCgq+4XPbZu/IS2VhEX/3SAB2RWsWiR9FwdXdTUFK36M0ZZkzQNiycxmO2cQhs HBmZCjkAmL+NRtVGKgJcMBzxInNvd3f4nHmlanMA= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Aldy Hernandez To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org Subject: [gcc/devel/ranger] libstdc++: Add [range.istream] X-Act-Checkin: gcc X-Git-Author: Patrick Palka X-Git-Refname: refs/heads/devel/ranger X-Git-Oldrev: 55d4cbcba8f1c74fa90ed53059114ccaaf549ad7 X-Git-Newrev: b7903d9f5beb5db440e56fa057d32c6f13f7c5ec Message-Id: <20200617184229.1AD903939C38@sourceware.org> Date: Wed, 17 Jun 2020 18:42:29 +0000 (GMT) X-BeenThere: libstdc++-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libstdc++-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 17 Jun 2020 18:42:29 -0000 https://gcc.gnu.org/g:b7903d9f5beb5db440e56fa057d32c6f13f7c5ec commit b7903d9f5beb5db440e56fa057d32c6f13f7c5ec Author: Patrick Palka 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 b374eff7408..4e010016a03 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,9 @@ 2020-02-07 Patrick Palka + * 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 and . (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 9f4fa3414d0..dd0c5cf6aa7 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 + concept __stream_extractable + = requires(basic_istream<_CharT, _Traits>& is, _Val& t) { is >> t; }; + } // namespace __detail + + template + requires default_initializable<_Val> + && __detail::__stream_extractable<_Val, _CharT, _Traits> + class basic_istream_view + : public view_interface> + { + 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 + 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..1729459bce3 --- /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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include +#include +#include +#include + +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(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(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(input) | views::take_while(small); + VERIFY( ranges::equal(v, (int[]){0,1,2,3,4}) ); +} + +int +main() +{ + test01(); + test02(); + test03(); +}