Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
implement `std::ranges::basic_istream_view` and `std::views::istream`. Although the view itself is constexpr, the constructor argument is a base class std::istream where its ctor/dtor are not constexpr. So no tests are performed in constexpr Differential Revision: https://reviews.llvm.org/D133317
- Loading branch information
Showing
22 changed files
with
885 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
// -*- C++ -*- | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
#ifndef _LIBCPP___RANGES_ISTREAM_VIEW_H | ||
#define _LIBCPP___RANGES_ISTREAM_VIEW_H | ||
|
||
#include <__concepts/constructible.h> | ||
#include <__concepts/derived_from.h> | ||
#include <__concepts/movable.h> | ||
#include <__config> | ||
#include <__iterator/default_sentinel.h> | ||
#include <__iterator/iterator_traits.h> | ||
#include <__memory/addressof.h> | ||
#include <__ranges/view_interface.h> | ||
#include <__type_traits/remove_cvref.h> | ||
#include <__utility/forward.h> | ||
#include <cstddef> | ||
#include <iosfwd> | ||
|
||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
# pragma GCC system_header | ||
#endif | ||
|
||
#if _LIBCPP_STD_VER >= 20 | ||
|
||
_LIBCPP_BEGIN_NAMESPACE_STD | ||
|
||
namespace ranges { | ||
|
||
template <class _Val, class _CharT, class _Traits> | ||
concept __stream_extractable = requires(basic_istream<_CharT, _Traits>& __is, _Val& __t) { __is >> __t; }; | ||
|
||
template <movable _Val, class _CharT, class _Traits = char_traits<_CharT>> | ||
requires default_initializable<_Val> && __stream_extractable<_Val, _CharT, _Traits> | ||
class basic_istream_view : public view_interface<basic_istream_view<_Val, _CharT, _Traits>> { | ||
public: | ||
_LIBCPP_HIDE_FROM_ABI constexpr explicit basic_istream_view(basic_istream<_CharT, _Traits>& __stream) | ||
: __stream_(std::addressof(__stream)) {} | ||
|
||
_LIBCPP_HIDE_FROM_ABI constexpr auto begin() { | ||
*__stream_ >> __value_; | ||
return __iterator{*this}; | ||
} | ||
|
||
_LIBCPP_HIDE_FROM_ABI constexpr default_sentinel_t end() const noexcept { return default_sentinel; } | ||
|
||
private: | ||
class __iterator; | ||
|
||
basic_istream<_CharT, _Traits>* __stream_; | ||
_LIBCPP_NO_UNIQUE_ADDRESS _Val __value_ = _Val(); | ||
}; | ||
|
||
template <movable _Val, class _CharT, class _Traits> | ||
requires default_initializable<_Val> && __stream_extractable<_Val, _CharT, _Traits> | ||
class basic_istream_view<_Val, _CharT, _Traits>::__iterator { | ||
public: | ||
using iterator_concept = input_iterator_tag; | ||
using difference_type = ptrdiff_t; | ||
using value_type = _Val; | ||
|
||
_LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(basic_istream_view& __parent) noexcept | ||
: __parent_(std::addressof(__parent)) {} | ||
|
||
__iterator(const __iterator&) = delete; | ||
_LIBCPP_HIDE_FROM_ABI __iterator(__iterator&&) = default; | ||
|
||
__iterator& operator=(const __iterator&) = delete; | ||
_LIBCPP_HIDE_FROM_ABI __iterator& operator=(__iterator&&) = default; | ||
|
||
_LIBCPP_HIDE_FROM_ABI __iterator& operator++() { | ||
*__parent_->__stream_ >> __parent_->__value_; | ||
return *this; | ||
} | ||
|
||
_LIBCPP_HIDE_FROM_ABI void operator++(int) { ++*this; } | ||
|
||
_LIBCPP_HIDE_FROM_ABI _Val& operator*() const { return __parent_->__value_; } | ||
|
||
_LIBCPP_HIDE_FROM_ABI friend bool operator==(const __iterator& __x, default_sentinel_t) { | ||
return !*__x.__get_parent_stream(); | ||
} | ||
|
||
private: | ||
basic_istream_view* __parent_; | ||
|
||
_LIBCPP_HIDE_FROM_ABI constexpr basic_istream<_CharT, _Traits>* __get_parent_stream() const { | ||
return __parent_->__stream_; | ||
} | ||
}; | ||
|
||
template <class _Val> | ||
using istream_view = basic_istream_view<_Val, char>; | ||
|
||
#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS | ||
template <class _Val> | ||
using wistream_view = basic_istream_view<_Val, wchar_t>; | ||
#endif | ||
|
||
namespace views { | ||
namespace __istream { | ||
|
||
// clang-format off | ||
template <class _Tp> | ||
struct __fn { | ||
template <class _Up, class _UnCVRef = remove_cvref_t<_Up>> | ||
requires derived_from<_UnCVRef, basic_istream<typename _UnCVRef::char_type, | ||
typename _UnCVRef::traits_type>> | ||
_LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Up&& __u) const | ||
noexcept(noexcept(basic_istream_view<_Tp, typename _UnCVRef::char_type, | ||
typename _UnCVRef::traits_type>(std::forward<_Up>(__u)))) | ||
-> decltype( basic_istream_view<_Tp, typename _UnCVRef::char_type, | ||
typename _UnCVRef::traits_type>(std::forward<_Up>(__u))) | ||
{ return basic_istream_view<_Tp, typename _UnCVRef::char_type, | ||
typename _UnCVRef::traits_type>(std::forward<_Up>(__u)); | ||
} | ||
}; | ||
// clang-format on | ||
|
||
} // namespace __istream | ||
|
||
inline namespace __cpo { | ||
template <class _Tp> | ||
inline constexpr auto istream = __istream::__fn<_Tp>{}; | ||
} // namespace __cpo | ||
} // namespace views | ||
|
||
} // namespace ranges | ||
|
||
_LIBCPP_END_NAMESPACE_STD | ||
|
||
#endif // _LIBCPP_STD_VER >= 20 | ||
|
||
#endif // _LIBCPP___RANGES_ISTREAM_VIEW_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
.../test/libcxx/ranges/range.factories/range.istream.view/no_unique_address.compile.pass.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// UNSUPPORTED: no-localization | ||
// UNSUPPORTED: c++03, c++11, c++14, c++17 | ||
|
||
// clang-cl and cl currently don't support [[no_unique_address]] | ||
// XFAIL: msvc | ||
|
||
// Test the libc++ extension that the value stored in `std::ranges::istream_view` has been marked | ||
// as _LIBCPP_NO_UNIQUE_ADDRESS | ||
|
||
#include <istream> | ||
#include <ranges> | ||
|
||
struct Empty { | ||
friend std::istream& operator>>(std::istream& i, Empty const&) { return i; } | ||
}; | ||
|
||
static_assert(sizeof(std::ranges::istream_view<Empty>) == sizeof(void*)); | ||
|
58 changes: 58 additions & 0 deletions
58
libcxx/test/std/ranges/range.factories/range.istream.view/begin.pass.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// UNSUPPORTED: no-localization | ||
// UNSUPPORTED: c++03, c++11, c++14, c++17 | ||
|
||
// constexpr auto begin(); | ||
|
||
#include <cassert> | ||
#include <ranges> | ||
#include <sstream> | ||
|
||
#include "test_macros.h" | ||
#include "utils.h" | ||
|
||
template <class T> | ||
concept HasBegin = requires(T t) { t.begin(); }; | ||
|
||
static_assert(HasBegin<std::ranges::istream_view<int>>); | ||
static_assert(!HasBegin<const std::ranges::istream_view<int>>); | ||
|
||
#ifndef TEST_HAS_NO_WIDE_CHARACTERS | ||
static_assert(HasBegin<std::ranges::wistream_view<int>>); | ||
static_assert(!HasBegin<const std::ranges::wistream_view<int>>); | ||
#endif | ||
|
||
template <class CharT> | ||
void test() { | ||
// begin should read the first element | ||
{ | ||
auto iss = make_string_stream<CharT>("12 3"); | ||
std::ranges::basic_istream_view<int, CharT> isv{iss}; | ||
auto it = isv.begin(); | ||
assert(*it == 12); | ||
} | ||
|
||
// empty stream | ||
{ | ||
auto iss = make_string_stream<CharT>(""); | ||
std::ranges::basic_istream_view<int, CharT> isv{iss}; | ||
auto it = isv.begin(); | ||
assert(it == isv.end()); | ||
} | ||
} | ||
|
||
int main(int, char**) { | ||
test<char>(); | ||
#ifndef TEST_HAS_NO_WIDE_CHARACTERS | ||
test<wchar_t>(); | ||
#endif | ||
|
||
return 0; | ||
} |
46 changes: 46 additions & 0 deletions
46
libcxx/test/std/ranges/range.factories/range.istream.view/cpo.pass.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// UNSUPPORTED: no-localization | ||
// UNSUPPORTED: c++03, c++11, c++14, c++17 | ||
|
||
// std::views::istream<T> | ||
|
||
#include <cassert> | ||
#include <ranges> | ||
#include <sstream> | ||
|
||
#include "test_macros.h" | ||
#include "utils.h" | ||
|
||
static_assert(!std::is_invocable_v<decltype((std::views::istream<int>))>); | ||
static_assert(std::is_invocable_v<decltype((std::views::istream<int>)), std::istream&>); | ||
static_assert(!std::is_invocable_v<decltype((std::views::istream<int>)), const std::istream&>); | ||
static_assert(!std::is_invocable_v<decltype((std::views::istream<int>)), int>); | ||
|
||
#ifndef TEST_HAS_NO_WIDE_CHARACTERS | ||
static_assert(std::is_invocable_v<decltype((std::views::istream<int>)), std::wistream&>); | ||
static_assert(!std::is_invocable_v<decltype((std::views::istream<int>)), const std::wistream&>); | ||
#endif | ||
|
||
template <class CharT> | ||
void test() { | ||
auto iss = make_string_stream<CharT>("12 3"); | ||
auto isv = std::views::istream<int>(iss); | ||
auto it = isv.begin(); | ||
assert(*it == 12); | ||
} | ||
|
||
int main(int, char**) { | ||
test<char>(); | ||
#ifndef TEST_HAS_NO_WIDE_CHARACTERS | ||
test<wchar_t>(); | ||
#endif | ||
|
||
return 0; | ||
} |
Oops, something went wrong.