From: Patrick Palka Date: Fri, 7 Feb 2020 00:24:03 +0000 (-0500) Subject: libstdc++: Add [range.istream] X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b7903d9f5beb5db440e56fa057d32c6f13f7c5ec;p=gcc.git 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 --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(); +}