libstdc++/ranges: Implement various small LWG issues
Checks
Context |
Check |
Description |
linaro-tcwg-bot/tcwg_gcc_build--master-arm |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_gcc_check--master-arm |
success
|
Test passed
|
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 |
success
|
Test passed
|
Commit Message
Tested on x86_64-pc-linux-gnu, does this look OK for trunk/14 and perhaps
13?
-- >8 --
This implements the following small LWG issues:
3848. adjacent_view, adjacent_transform_view and slide_view missing base accessor
3851. chunk_view::inner-iterator missing custom iter_move and iter_swap
3947. Unexpected constraints on adjacent_transform_view::base()
4001. iota_view should provide empty
4012. common_view::begin/end are missing the simple-view check
4013. lazy_split_view::outer-iterator::value_type should not provide default constructor
4035. single_view should provide empty
4053. Unary call to std::views::repeat does not decay the argument
4054. Repeating a repeat_view should repeat the view
libstdc++-v3/ChangeLog:
* include/std/ranges (single_view::empty): Define as per LWG 4035.
(iota_view::empty): Define as per LWG 4001.
(lazy_split_view::_OuterIter::value_type): Remove default
constructor and make other constructor private as per LWG 4013.
(common_view::begin): Disable non-const overload for simple
views as per LWG 4012.
(common_view::end): Likewise.
(adjacent_view::base): Define as per LWG 3848.
(adjacent_transform_view::base): Likewise.
(chunk_view::_InnerIter::iter_move): Define as per LWG 3851.
(chunk_view::_InnerIter::itep_swap): Likewise.
(slide_view::base): Define as per LWG 3848.
(repeat_view): Adjust deduction guide as per LWG 4053.
(_Repeat::operator()): Adjust single-parameter overload
as per LWG 4054.
* testsuite/std/ranges/adaptors/adjacent/1.cc: Verify existence
of base member function.
* testsuite/std/ranges/adaptors/adjacent_transform/1.cc: Likewise.
* testsuite/std/ranges/adaptors/chunk/1.cc: Test LWG 3851 example.
* testsuite/std/ranges/adaptors/slide/1.cc: Verify existence of
base member function.
* testsuite/std/ranges/iota/iota_view.cc: Test LWG 4001 example.
* testsuite/std/ranges/repeat/1.cc: Test LWG 4053/4054 examples.
---
libstdc++-v3/include/std/ranges | 84 +++++++++++++++++--
.../std/ranges/adaptors/adjacent/1.cc | 3 +
.../ranges/adaptors/adjacent_transform/1.cc | 3 +
.../testsuite/std/ranges/adaptors/chunk/1.cc | 15 ++++
.../testsuite/std/ranges/adaptors/slide/1.cc | 3 +
.../testsuite/std/ranges/iota/iota_view.cc | 12 +++
libstdc++-v3/testsuite/std/ranges/repeat/1.cc | 23 +++++
7 files changed, 135 insertions(+), 8 deletions(-)
Comments
On Fri, 4 Oct 2024 at 03:09, Patrick Palka <ppalka@redhat.com> wrote:
>
> Tested on x86_64-pc-linux-gnu, does this look OK for trunk/14 and perhaps
> 13?
OK for all, thanks.
>
> -- >8 --
>
> This implements the following small LWG issues:
>
> 3848. adjacent_view, adjacent_transform_view and slide_view missing base accessor
> 3851. chunk_view::inner-iterator missing custom iter_move and iter_swap
> 3947. Unexpected constraints on adjacent_transform_view::base()
> 4001. iota_view should provide empty
> 4012. common_view::begin/end are missing the simple-view check
> 4013. lazy_split_view::outer-iterator::value_type should not provide default constructor
> 4035. single_view should provide empty
> 4053. Unary call to std::views::repeat does not decay the argument
> 4054. Repeating a repeat_view should repeat the view
>
> libstdc++-v3/ChangeLog:
>
> * include/std/ranges (single_view::empty): Define as per LWG 4035.
> (iota_view::empty): Define as per LWG 4001.
> (lazy_split_view::_OuterIter::value_type): Remove default
> constructor and make other constructor private as per LWG 4013.
> (common_view::begin): Disable non-const overload for simple
> views as per LWG 4012.
> (common_view::end): Likewise.
> (adjacent_view::base): Define as per LWG 3848.
> (adjacent_transform_view::base): Likewise.
> (chunk_view::_InnerIter::iter_move): Define as per LWG 3851.
> (chunk_view::_InnerIter::itep_swap): Likewise.
> (slide_view::base): Define as per LWG 3848.
> (repeat_view): Adjust deduction guide as per LWG 4053.
> (_Repeat::operator()): Adjust single-parameter overload
> as per LWG 4054.
> * testsuite/std/ranges/adaptors/adjacent/1.cc: Verify existence
> of base member function.
> * testsuite/std/ranges/adaptors/adjacent_transform/1.cc: Likewise.
> * testsuite/std/ranges/adaptors/chunk/1.cc: Test LWG 3851 example.
> * testsuite/std/ranges/adaptors/slide/1.cc: Verify existence of
> base member function.
> * testsuite/std/ranges/iota/iota_view.cc: Test LWG 4001 example.
> * testsuite/std/ranges/repeat/1.cc: Test LWG 4053/4054 examples.
> ---
> libstdc++-v3/include/std/ranges | 84 +++++++++++++++++--
> .../std/ranges/adaptors/adjacent/1.cc | 3 +
> .../ranges/adaptors/adjacent_transform/1.cc | 3 +
> .../testsuite/std/ranges/adaptors/chunk/1.cc | 15 ++++
> .../testsuite/std/ranges/adaptors/slide/1.cc | 3 +
> .../testsuite/std/ranges/iota/iota_view.cc | 12 +++
> libstdc++-v3/testsuite/std/ranges/repeat/1.cc | 23 +++++
> 7 files changed, 135 insertions(+), 8 deletions(-)
>
> diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
> index 30f45e0a750..6e6e3b97d82 100644
> --- a/libstdc++-v3/include/std/ranges
> +++ b/libstdc++-v3/include/std/ranges
> @@ -335,6 +335,12 @@ namespace ranges
> end() const noexcept
> { return data() + 1; }
>
> + // _GLIBCXX_RESOLVE_LIB_DEFECTS
> + // 4035. single_view should provide empty
> + static constexpr bool
> + empty() noexcept
> + { return false; }
> +
> static constexpr size_t
> size() noexcept
> { return 1; }
> @@ -695,6 +701,12 @@ namespace ranges
> end() const requires same_as<_Winc, _Bound>
> { return _Iterator{_M_bound}; }
>
> + // _GLIBCXX_RESOLVE_LIB_DEFECTS
> + // 4001. iota_view should provide empty
> + constexpr bool
> + empty() const
> + { return _M_value == _M_bound; }
> +
> constexpr auto
> size() const
> requires (same_as<_Winc, _Bound> && __detail::__advanceable<_Winc>)
> @@ -3349,14 +3361,17 @@ namespace views::__adaptor
> private:
> _OuterIter _M_i = _OuterIter();
>
> - public:
> - value_type() = default;
> -
> + // _GLIBCXX_RESOLVE_LIB_DEFECTS
> + // 4013. lazy_split_view::outer-iterator::value_type should not
> + // provide default constructor
> constexpr explicit
> value_type(_OuterIter __i)
> : _M_i(std::move(__i))
> { }
>
> + friend _OuterIter;
> +
> + public:
> constexpr _InnerIter<_Const>
> begin() const
> { return _InnerIter<_Const>{_M_i}; }
> @@ -3948,8 +3963,10 @@ namespace views::__adaptor
> base() &&
> { return std::move(_M_base); }
>
> + // _GLIBCXX_RESOLVE_LIB_DEFECTS
> + // 4012. common_view::begin/end are missing the simple-view check
> constexpr auto
> - begin()
> + begin() requires (!__detail::__simple_view<_Vp>)
> {
> if constexpr (random_access_range<_Vp> && sized_range<_Vp>)
> return ranges::begin(_M_base);
> @@ -3969,7 +3986,7 @@ namespace views::__adaptor
> }
>
> constexpr auto
> - end()
> + end() requires (!__detail::__simple_view<_Vp>)
> {
> if constexpr (random_access_range<_Vp> && sized_range<_Vp>)
> return ranges::begin(_M_base) + ranges::size(_M_base);
> @@ -5316,6 +5333,16 @@ namespace views::__adaptor
> : _M_base(std::move(__base))
> { }
>
> + // _GLIBCXX_RESOLVE_LIB_DEFECTS
> + // 3848. adjacent_view, adjacent_transform_view and slide_view missing base accessor
> + constexpr _Vp
> + base() const & requires copy_constructible<_Vp>
> + { return _M_base; }
> +
> + constexpr _Vp
> + base() &&
> + { return std::move(_M_base); }
> +
> constexpr auto
> begin() requires (!__detail::__simple_view<_Vp>)
> { return _Iterator<false>(ranges::begin(_M_base), ranges::end(_M_base)); }
> @@ -5709,6 +5736,17 @@ namespace views::__adaptor
> : _M_fun(std::move(__fun)), _M_inner(std::move(__base))
> { }
>
> + // _GLIBCXX_RESOLVE_LIB_DEFECTS
> + // 3848. adjacent_view, adjacent_transform_view and slide_view missing base accessor
> + // 3947. Unexpected constraints on adjacent_transform_view::base()
> + constexpr _Vp
> + base() const & requires copy_constructible<_Vp>
> + { return _M_inner.base(); }
> +
> + constexpr _Vp
> + base() &&
> + { return std::move(_M_inner.base()); }
> +
> constexpr auto
> begin()
> { return _Iterator<false>(*this, _M_inner.begin()); }
> @@ -6236,6 +6274,20 @@ namespace views::__adaptor
> operator-(const _InnerIter& __x, default_sentinel_t __y)
> requires sized_sentinel_for<sentinel_t<_Vp>, iterator_t<_Vp>>
> { return -(__y - __x); }
> +
> + // _GLIBCXX_RESOLVE_LIB_DEFECTS
> + // 3851. chunk_view::inner-iterator missing custom iter_move and iter_swap
> + friend constexpr range_rvalue_reference_t<_Vp>
> + iter_move(const _InnerIter& __i)
> + noexcept(noexcept(ranges::iter_move(*__i._M_parent->_M_current)))
> + { return ranges::iter_move(*__i._M_parent->_M_current); }
> +
> + friend constexpr void
> + iter_swap(const _InnerIter& __x, const _InnerIter& __y)
> + noexcept(noexcept(ranges::iter_swap(*__x._M_parent->_M_current,
> + *__x._M_parent->_M_current)))
> + requires indirectly_swappable<iterator_t<_Vp>>
> + { return ranges::iter_swap(*__x._M_parent->_M_current, *__y._M_parent->_M_current); }
> };
>
> template<view _Vp>
> @@ -6577,6 +6629,16 @@ namespace views::__adaptor
> : _M_base(std::move(__base)), _M_n(__n)
> { __glibcxx_assert(__n > 0); }
>
> + // _GLIBCXX_RESOLVE_LIB_DEFECTS
> + // 3848. adjacent_view, adjacent_transform_view and slide_view missing base accessor
> + constexpr _Vp
> + base() const & requires copy_constructible<_Vp>
> + { return _M_base; }
> +
> + constexpr _Vp
> + base() &&
> + { return std::move(_M_base); }
> +
> constexpr auto
> begin() requires (!(__detail::__simple_view<_Vp>
> && __detail::__slide_caches_nothing<const _Vp>))
> @@ -7692,8 +7754,10 @@ namespace views::__adaptor
> { return __detail::__to_unsigned_like(_M_bound); }
> };
>
> - template<typename _Tp, typename _Bound>
> - repeat_view(_Tp, _Bound) -> repeat_view<_Tp, _Bound>;
> + // _GLIBCXX_RESOLVE_LIB_DEFECTS
> + // 4053. Unary call to std::views::repeat does not decay the argument
> + template<typename _Tp, typename _Bound = unreachable_sentinel_t>
> + repeat_view(_Tp, _Bound = _Bound()) -> repeat_view<_Tp, _Bound>;
>
> template<move_constructible _Tp, semiregular _Bound>
> requires is_object_v<_Tp> && same_as<_Tp, remove_cv_t<_Tp>>
> @@ -7840,7 +7904,11 @@ namespace views::__adaptor
> requires __detail::__can_repeat_view<_Tp>
> constexpr auto
> operator() [[nodiscard]] (_Tp&& __value) const
> - { return repeat_view(std::forward<_Tp>(__value)); }
> + {
> + // _GLIBCXX_RESOLVE_LIB_DEFECTS
> + // 4054. Repeating a repeat_view should repeat the view
> + return repeat_view<decay_t<_Tp>>(std::forward<_Tp>(__value));
> + }
>
> template<typename _Tp, typename _Bound>
> requires __detail::__can_bounded_repeat_view<_Tp, _Bound>
> diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent/1.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent/1.cc
> index b83743a745c..085cd4a8c54 100644
> --- a/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent/1.cc
> +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent/1.cc
> @@ -47,6 +47,9 @@ test01()
> VERIFY( &std::get<2>(v3[i]) == &y[i] + 2 );
> }
>
> + // LWG 3848 - adjacent_view etc missing base accessor
> + v3.base();
> +
> const auto v5 = y | views::adjacent<5>;
> VERIFY( ranges::equal(v5, views::single(std::make_tuple(1, 2, 3, 4, 5))) );
>
> diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent_transform/1.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent_transform/1.cc
> index 6aeedbaa648..a5791b3da70 100644
> --- a/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent_transform/1.cc
> +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent_transform/1.cc
> @@ -39,6 +39,9 @@ test01()
> VERIFY( ranges::size(v3) == 4 );
> VERIFY( ranges::equal(v3, (int[]){3, 4, 5, 6}) );
>
> + // LWG 3848 - adjacent_transform_view etc missing base accessor
> + v3.base();
> +
> const auto v6 = y | views::adjacent_transform<6>([](auto...) { return 0; });
> VERIFY( ranges::equal(v6, (int[]){0}) );
>
> diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/chunk/1.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/chunk/1.cc
> index 90eb608ca5e..82f9f1b674c 100644
> --- a/libstdc++-v3/testsuite/std/ranges/adaptors/chunk/1.cc
> +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/chunk/1.cc
> @@ -8,6 +8,7 @@
> #endif
>
> #include <algorithm>
> +#include <sstream>
> #include <vector>
> #include <testsuite_hooks.h>
> #include <testsuite_iterators.h>
> @@ -76,10 +77,24 @@ test02()
> VERIFY( ranges::equal(wrapper(x) | views::chunk(i) | views::join, x) );
> }
>
> +void
> +test03()
> +{
> + // LWG 3851 - chunk_view::inner-iterator missing custom iter_move and iter_swap
> + auto ints = std::istringstream{"0 1 2 3 4"};
> + std::vector<std::string> vs{"the", "quick", "brown", "fox"};
> + auto r = views::zip(vs, views::istream<int>(ints)) | views::chunk(2) | views::join;
> + std::vector<std::tuple<std::string, int>> res;
> + ranges::copy(std::move_iterator(r.begin()), std::move_sentinel(r.end()),
> + std::back_inserter(res));
> + VERIFY( vs.front().empty() );
> +}
> +
> int
> main()
> {
> static_assert(test01());
> test02<__gnu_test::test_input_range<int>>();
> test02<__gnu_test::test_forward_range<int>>();
> + test03();
> }
> diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/slide/1.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/slide/1.cc
> index bafe9fbc4bf..a5d94ea6406 100644
> --- a/libstdc++-v3/testsuite/std/ranges/adaptors/slide/1.cc
> +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/slide/1.cc
> @@ -50,6 +50,9 @@ test01()
> VERIFY( &v3[i][2] == &y[i] + 2 );
> }
>
> + // LWG 3848 - slide_view etc missing base accessor
> + v3.base();
> +
> const auto v5 = y | views::slide(5);
> VERIFY( ranges::size(v5) == 1 );
> VERIFY( ranges::equal(v5 | views::join, y) );
> diff --git a/libstdc++-v3/testsuite/std/ranges/iota/iota_view.cc b/libstdc++-v3/testsuite/std/ranges/iota/iota_view.cc
> index bec4174a3da..9db61a76596 100644
> --- a/libstdc++-v3/testsuite/std/ranges/iota/iota_view.cc
> +++ b/libstdc++-v3/testsuite/std/ranges/iota/iota_view.cc
> @@ -19,6 +19,7 @@
>
> #include <algorithm>
> #include <ranges>
> +#include <vector>
> #include <testsuite_hooks.h>
>
> void
> @@ -118,6 +119,16 @@ test07()
> static_assert(!requires { iota(nullptr, nullptr); });
> }
>
> +void
> +test08()
> +{
> + // LWC 4001 - iota_view should provide empty
> + std::vector<int> v;
> + auto it = std::back_inserter(v);
> + auto r = std::views::iota(it);
> + VERIFY( !r.empty() );
> +}
> +
> int
> main()
> {
> @@ -128,4 +139,5 @@ main()
> test05();
> test06();
> test07();
> + test08();
> }
> diff --git a/libstdc++-v3/testsuite/std/ranges/repeat/1.cc b/libstdc++-v3/testsuite/std/ranges/repeat/1.cc
> index cad8c8dcbe7..eb0c848e9ce 100644
> --- a/libstdc++-v3/testsuite/std/ranges/repeat/1.cc
> +++ b/libstdc++-v3/testsuite/std/ranges/repeat/1.cc
> @@ -151,6 +151,27 @@ test07()
> auto d2 = std::views::repeat(std::make_unique<int>(5), 4) | std::views::drop(2);
> }
>
> +void
> +test08()
> +{
> + // LWG 4053 - Unary call to std::views::repeat does not decay the argument
> + using type = ranges::repeat_view<const char*>;
> + using type = decltype(views::repeat("foo", std::unreachable_sentinel));
> + using type = decltype(views::repeat(+"foo", std::unreachable_sentinel));
> + using type = decltype(views::repeat("foo"));
> + using type = decltype(views::repeat(+"foo"));
> +}
> +
> +void
> +test09()
> +{
> + // LWG 4054 - Repeating a repeat_view should repeat the view
> + auto v = views::repeat(views::repeat(5));
> + using type = decltype(v);
> + using type = ranges::repeat_view<ranges::repeat_view<int>>;
> + VERIFY( v[0][0] == 5 );
> +}
> +
> int
> main()
> {
> @@ -161,4 +182,6 @@ main()
> test05();
> test06();
> test07();
> + test08();
> + test09();
> }
> --
> 2.47.0.rc1
>
@@ -335,6 +335,12 @@ namespace ranges
end() const noexcept
{ return data() + 1; }
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4035. single_view should provide empty
+ static constexpr bool
+ empty() noexcept
+ { return false; }
+
static constexpr size_t
size() noexcept
{ return 1; }
@@ -695,6 +701,12 @@ namespace ranges
end() const requires same_as<_Winc, _Bound>
{ return _Iterator{_M_bound}; }
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4001. iota_view should provide empty
+ constexpr bool
+ empty() const
+ { return _M_value == _M_bound; }
+
constexpr auto
size() const
requires (same_as<_Winc, _Bound> && __detail::__advanceable<_Winc>)
@@ -3349,14 +3361,17 @@ namespace views::__adaptor
private:
_OuterIter _M_i = _OuterIter();
- public:
- value_type() = default;
-
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4013. lazy_split_view::outer-iterator::value_type should not
+ // provide default constructor
constexpr explicit
value_type(_OuterIter __i)
: _M_i(std::move(__i))
{ }
+ friend _OuterIter;
+
+ public:
constexpr _InnerIter<_Const>
begin() const
{ return _InnerIter<_Const>{_M_i}; }
@@ -3948,8 +3963,10 @@ namespace views::__adaptor
base() &&
{ return std::move(_M_base); }
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4012. common_view::begin/end are missing the simple-view check
constexpr auto
- begin()
+ begin() requires (!__detail::__simple_view<_Vp>)
{
if constexpr (random_access_range<_Vp> && sized_range<_Vp>)
return ranges::begin(_M_base);
@@ -3969,7 +3986,7 @@ namespace views::__adaptor
}
constexpr auto
- end()
+ end() requires (!__detail::__simple_view<_Vp>)
{
if constexpr (random_access_range<_Vp> && sized_range<_Vp>)
return ranges::begin(_M_base) + ranges::size(_M_base);
@@ -5316,6 +5333,16 @@ namespace views::__adaptor
: _M_base(std::move(__base))
{ }
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3848. adjacent_view, adjacent_transform_view and slide_view missing base accessor
+ constexpr _Vp
+ base() const & requires copy_constructible<_Vp>
+ { return _M_base; }
+
+ constexpr _Vp
+ base() &&
+ { return std::move(_M_base); }
+
constexpr auto
begin() requires (!__detail::__simple_view<_Vp>)
{ return _Iterator<false>(ranges::begin(_M_base), ranges::end(_M_base)); }
@@ -5709,6 +5736,17 @@ namespace views::__adaptor
: _M_fun(std::move(__fun)), _M_inner(std::move(__base))
{ }
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3848. adjacent_view, adjacent_transform_view and slide_view missing base accessor
+ // 3947. Unexpected constraints on adjacent_transform_view::base()
+ constexpr _Vp
+ base() const & requires copy_constructible<_Vp>
+ { return _M_inner.base(); }
+
+ constexpr _Vp
+ base() &&
+ { return std::move(_M_inner.base()); }
+
constexpr auto
begin()
{ return _Iterator<false>(*this, _M_inner.begin()); }
@@ -6236,6 +6274,20 @@ namespace views::__adaptor
operator-(const _InnerIter& __x, default_sentinel_t __y)
requires sized_sentinel_for<sentinel_t<_Vp>, iterator_t<_Vp>>
{ return -(__y - __x); }
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3851. chunk_view::inner-iterator missing custom iter_move and iter_swap
+ friend constexpr range_rvalue_reference_t<_Vp>
+ iter_move(const _InnerIter& __i)
+ noexcept(noexcept(ranges::iter_move(*__i._M_parent->_M_current)))
+ { return ranges::iter_move(*__i._M_parent->_M_current); }
+
+ friend constexpr void
+ iter_swap(const _InnerIter& __x, const _InnerIter& __y)
+ noexcept(noexcept(ranges::iter_swap(*__x._M_parent->_M_current,
+ *__x._M_parent->_M_current)))
+ requires indirectly_swappable<iterator_t<_Vp>>
+ { return ranges::iter_swap(*__x._M_parent->_M_current, *__y._M_parent->_M_current); }
};
template<view _Vp>
@@ -6577,6 +6629,16 @@ namespace views::__adaptor
: _M_base(std::move(__base)), _M_n(__n)
{ __glibcxx_assert(__n > 0); }
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3848. adjacent_view, adjacent_transform_view and slide_view missing base accessor
+ constexpr _Vp
+ base() const & requires copy_constructible<_Vp>
+ { return _M_base; }
+
+ constexpr _Vp
+ base() &&
+ { return std::move(_M_base); }
+
constexpr auto
begin() requires (!(__detail::__simple_view<_Vp>
&& __detail::__slide_caches_nothing<const _Vp>))
@@ -7692,8 +7754,10 @@ namespace views::__adaptor
{ return __detail::__to_unsigned_like(_M_bound); }
};
- template<typename _Tp, typename _Bound>
- repeat_view(_Tp, _Bound) -> repeat_view<_Tp, _Bound>;
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4053. Unary call to std::views::repeat does not decay the argument
+ template<typename _Tp, typename _Bound = unreachable_sentinel_t>
+ repeat_view(_Tp, _Bound = _Bound()) -> repeat_view<_Tp, _Bound>;
template<move_constructible _Tp, semiregular _Bound>
requires is_object_v<_Tp> && same_as<_Tp, remove_cv_t<_Tp>>
@@ -7840,7 +7904,11 @@ namespace views::__adaptor
requires __detail::__can_repeat_view<_Tp>
constexpr auto
operator() [[nodiscard]] (_Tp&& __value) const
- { return repeat_view(std::forward<_Tp>(__value)); }
+ {
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4054. Repeating a repeat_view should repeat the view
+ return repeat_view<decay_t<_Tp>>(std::forward<_Tp>(__value));
+ }
template<typename _Tp, typename _Bound>
requires __detail::__can_bounded_repeat_view<_Tp, _Bound>
@@ -47,6 +47,9 @@ test01()
VERIFY( &std::get<2>(v3[i]) == &y[i] + 2 );
}
+ // LWG 3848 - adjacent_view etc missing base accessor
+ v3.base();
+
const auto v5 = y | views::adjacent<5>;
VERIFY( ranges::equal(v5, views::single(std::make_tuple(1, 2, 3, 4, 5))) );
@@ -39,6 +39,9 @@ test01()
VERIFY( ranges::size(v3) == 4 );
VERIFY( ranges::equal(v3, (int[]){3, 4, 5, 6}) );
+ // LWG 3848 - adjacent_transform_view etc missing base accessor
+ v3.base();
+
const auto v6 = y | views::adjacent_transform<6>([](auto...) { return 0; });
VERIFY( ranges::equal(v6, (int[]){0}) );
@@ -8,6 +8,7 @@
#endif
#include <algorithm>
+#include <sstream>
#include <vector>
#include <testsuite_hooks.h>
#include <testsuite_iterators.h>
@@ -76,10 +77,24 @@ test02()
VERIFY( ranges::equal(wrapper(x) | views::chunk(i) | views::join, x) );
}
+void
+test03()
+{
+ // LWG 3851 - chunk_view::inner-iterator missing custom iter_move and iter_swap
+ auto ints = std::istringstream{"0 1 2 3 4"};
+ std::vector<std::string> vs{"the", "quick", "brown", "fox"};
+ auto r = views::zip(vs, views::istream<int>(ints)) | views::chunk(2) | views::join;
+ std::vector<std::tuple<std::string, int>> res;
+ ranges::copy(std::move_iterator(r.begin()), std::move_sentinel(r.end()),
+ std::back_inserter(res));
+ VERIFY( vs.front().empty() );
+}
+
int
main()
{
static_assert(test01());
test02<__gnu_test::test_input_range<int>>();
test02<__gnu_test::test_forward_range<int>>();
+ test03();
}
@@ -50,6 +50,9 @@ test01()
VERIFY( &v3[i][2] == &y[i] + 2 );
}
+ // LWG 3848 - slide_view etc missing base accessor
+ v3.base();
+
const auto v5 = y | views::slide(5);
VERIFY( ranges::size(v5) == 1 );
VERIFY( ranges::equal(v5 | views::join, y) );
@@ -19,6 +19,7 @@
#include <algorithm>
#include <ranges>
+#include <vector>
#include <testsuite_hooks.h>
void
@@ -118,6 +119,16 @@ test07()
static_assert(!requires { iota(nullptr, nullptr); });
}
+void
+test08()
+{
+ // LWC 4001 - iota_view should provide empty
+ std::vector<int> v;
+ auto it = std::back_inserter(v);
+ auto r = std::views::iota(it);
+ VERIFY( !r.empty() );
+}
+
int
main()
{
@@ -128,4 +139,5 @@ main()
test05();
test06();
test07();
+ test08();
}
@@ -151,6 +151,27 @@ test07()
auto d2 = std::views::repeat(std::make_unique<int>(5), 4) | std::views::drop(2);
}
+void
+test08()
+{
+ // LWG 4053 - Unary call to std::views::repeat does not decay the argument
+ using type = ranges::repeat_view<const char*>;
+ using type = decltype(views::repeat("foo", std::unreachable_sentinel));
+ using type = decltype(views::repeat(+"foo", std::unreachable_sentinel));
+ using type = decltype(views::repeat("foo"));
+ using type = decltype(views::repeat(+"foo"));
+}
+
+void
+test09()
+{
+ // LWG 4054 - Repeating a repeat_view should repeat the view
+ auto v = views::repeat(views::repeat(5));
+ using type = decltype(v);
+ using type = ranges::repeat_view<ranges::repeat_view<int>>;
+ VERIFY( v[0][0] == 5 );
+}
+
int
main()
{
@@ -161,4 +182,6 @@ main()
test05();
test06();
test07();
+ test08();
+ test09();
}