libstdc++: Implement C++20 range adaptors

This patch implements [range.adaptors].  It also includes the changes from P3280
and P3278 and P3323, without which many standard examples won't work.

The implementation is mostly dictated by the spec and there was not much room
for implementation discretion.  The most interesting part that was not specified
by the spec is the design of the range adaptors and range adaptor closures,
which I tried to design in a way that minimizes boilerplate and statefulness (so
that e.g. the composition of two stateless closures is stateless).

What is left unimplemented is caching of calls to begin() in filter_view,
drop_view and reverse_view, which is required to guarantee that begin() has
amortized constant time complexity.  I can implement this in a subsequent patch.

"Interesting" parts of the patch are marked with XXX comments.

libstdc++-v3/ChangeLog:

	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
	avoid what seems to be a bug in GCC.
	(__detail::__box): Give it defaulted copy and move constructors.
	(views::_Single::operator()): Mark constexpr.
	(views::_Iota::operator()): Mark constexpr.
	(__detail::Empty): Define.
	(views::_RangeAdaptor, views::_RangeAdaptorClosure, ref_view, all_view,
	views::all, filter_view, views::filter, transform_view,
	views::transform, take_view, views::take, take_while_view,
	views::take_while, drop_view, views::drop, join_view, views::join,
	__detail::require_constant, __detail::tiny_range, split_view,
	views::split, views::_Counted, views::counted, common_view,
	views::common, reverse_view, views::reverse,
	views::__detail::__is_reversible_subrange,
	views::__detail::__is_reverse_view, reverse_view, views::reverse,
	__detail::__has_tuple_element, elements_view, views::elements,
	views::keys, views::values): Define.
	* testsuite/std/ranges/adaptors/all.cc: New test.
	* testsuite/std/ranges/adaptors/common.cc: Likewise.
	* testsuite/std/ranges/adaptors/counted.cc: Likewise.
	* testsuite/std/ranges/adaptors/drop.cc: Likewise.
	* testsuite/std/ranges/adaptors/drop_while.cc: Likewise.
	* testsuite/std/ranges/adaptors/elements.cc: Likewise.
	* testsuite/std/ranges/adaptors/filter.cc: Likewise.
	* testsuite/std/ranges/adaptors/join.cc: Likewise.
	* testsuite/std/ranges/adaptors/reverse.cc: Likewise.
	* testsuite/std/ranges/adaptors/split.cc: Likewise.
	* testsuite/std/ranges/adaptors/take.cc: Likewise.
	* testsuite/std/ranges/adaptors/take_while.cc: Likewise.
	* testsuite/std/ranges/adaptors/transform.cc: Likewise.
This commit is contained in:
Patrick Palka 2020-01-30 17:37:07 -05:00
parent 0d57370c9c
commit cba9ef069e
15 changed files with 3531 additions and 5 deletions

View File

@ -1,3 +1,38 @@
2020-02-07 Patrick Palka <ppalka@redhat.com>
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
avoid what seems to be a bug in GCC.
(__detail::__box): Give it defaulted copy and move constructors.
(views::_Single::operator()): Mark constexpr.
(views::_Iota::operator()): Mark constexpr.
(__detail::Empty): Define.
(views::_RangeAdaptor, views::_RangeAdaptorClosure, ref_view, all_view,
views::all, filter_view, views::filter, transform_view,
views::transform, take_view, views::take, take_while_view,
views::take_while, drop_view, views::drop, join_view, views::join,
__detail::require_constant, __detail::tiny_range, split_view,
views::split, views::_Counted, views::counted, common_view,
views::common, reverse_view, views::reverse,
views::__detail::__is_reversible_subrange,
views::__detail::__is_reverse_view, reverse_view, views::reverse,
__detail::__has_tuple_element, elements_view, views::elements,
views::keys, views::values): Define.
* testsuite/std/ranges/adaptors/all.cc: New test.
* testsuite/std/ranges/adaptors/common.cc: Likewise.
* testsuite/std/ranges/adaptors/counted.cc: Likewise.
* testsuite/std/ranges/adaptors/drop.cc: Likewise.
* testsuite/std/ranges/adaptors/drop_while.cc: Likewise.
* testsuite/std/ranges/adaptors/elements.cc: Likewise.
* testsuite/std/ranges/adaptors/filter.cc: Likewise.
* testsuite/std/ranges/adaptors/join.cc: Likewise.
* testsuite/std/ranges/adaptors/reverse.cc: Likewise.
* testsuite/std/ranges/adaptors/split.cc: Likewise.
* testsuite/std/ranges/adaptors/take.cc: Likewise.
* testsuite/std/ranges/adaptors/take_while.cc: Likewise.
* testsuite/std/ranges/adaptors/transform.cc: Likewise.
2020-02-07 Jonathan Wakely <jwakely@redhat.com>
* libsupc++/compare (__cmp_cat::type): Define typedef for underlying

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,122 @@
// 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 <testsuite_hooks.h>
#include <testsuite_iterators.h>
namespace ranges = std::ranges;
namespace views = std::ranges::views;
void
test01()
{
int x[] = {1,2,3,4,5};
auto v = views::all(x);
static_assert(ranges::view<decltype(v)>);
static_assert(ranges::random_access_range<decltype(v)>);
VERIFY( ranges::size(v) == 5 );
VERIFY( ranges::size(x | views::all) == 5 );
VERIFY( ranges::size(v | views::all | views::all) == 5 );
VERIFY( ranges::size(v | (views::all | views::all)) == 5 );
ranges::reverse(v);
VERIFY( ranges::equal(v, (int[]){5,4,3,2,1}) );
}
void
test02()
{
int x[5] = { 0 };
int k = 0;
for (auto&& i : ranges::ref_view{x})
i += ++k;
VERIFY( ranges::equal(x, (int[]){1,2,3,4,5}) );
}
constexpr bool
test03()
{
std::array ints{0,1,2,3,4,5};
auto even = [] (int i) { return i%2==0; };
auto odd = [] (int i) { return i%2==1; };
auto square = [] (int i) { return i*i; };
int sum = 0;
for (auto v : (ints
| (views::all
| (views::filter(even)
| (views::filter(odd) | views::all)))
| views::transform(square)))
sum += v;
return sum == 0;
}
constexpr bool
test04()
{
auto odd = [] (int i) { return i%2==1; };
auto square = [] (int i) { return i*i; };
auto increment = [] (int i) { return i+1; };
auto small = [] (int i) { return i<30; };
auto non_negative = [] (int i) { return i>=0; };
auto negative = [] (int i) { return i<0; };
return ranges::equal(views::iota(-5)
| views::drop_while(negative)
| views::take_while(non_negative)
| views::transform(increment)
| views::filter(odd)
| views::take(3)
| views::all
| views::transform(square),
views::iota(-5)
| views::drop_while(negative)
| views::drop(1)
| views::filter(odd)
| views::transform(square)
| views::take_while(small)
| views::take_while(small));
}
static_assert(std::is_empty_v<decltype(views::common
| views::join
| views::all
| views::common
| views::keys
| views::reverse)>);
static_assert(sizeof(decltype(views::take(5) | views::drop(5)))
== sizeof(decltype(views::take(5)
| views::join
| views::common
| views::all
| views::keys
| views::drop(5)
| views::reverse)));
int
main()
{
test01();
test02();
static_assert(test03());
static_assert(test04());
}

View File

@ -0,0 +1,68 @@
// 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 <testsuite_hooks.h>
#include <testsuite_iterators.h>
using __gnu_test::test_range;
using __gnu_test::forward_iterator_wrapper;
namespace ranges = std::ranges;
namespace views = ranges::views;
void
test01()
{
int x[] = {1,2,1,3};
auto v = x | views::common;
VERIFY( std::count(v.begin(), v.end(), 1) == 2);
static_assert(ranges::common_range<decltype(v)>);
static_assert(ranges::view<decltype(v)>);
static_assert(ranges::random_access_range<decltype(v)>);
static_assert(std::same_as<decltype(v), decltype(views::common(v))>);
auto v2 = v | (views::common | views::common);
VERIFY( std::count(v2.begin(), v2.end(), 1) == 2);
}
void
test02()
{
int x[] = {1,2,1,3};
test_range<int, forward_iterator_wrapper> rx(x);
auto v = ranges::common_view(rx);
VERIFY( std::count(v.begin(), v.end(), 1) == 2);
static_assert(ranges::common_range<decltype(v)>);
static_assert(ranges::view<decltype(v)>);
static_assert(ranges::forward_range<decltype(v)>);
static_assert(std::same_as<decltype(v), decltype(views::common(v))>);
auto v2 = v | (views::common | views::common);
VERIFY( std::count(v2.begin(), v2.end(), 1) == 2);
}
int
main()
{
test01();
test02();
}

View File

@ -0,0 +1,64 @@
// 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 <testsuite_hooks.h>
#include <testsuite_iterators.h>
using __gnu_test::test_range;
using __gnu_test::forward_iterator_wrapper;
namespace ranges = std::ranges;
namespace views = ranges::views;
void
test01()
{
int x[] = {0,1,2,3,4,5,0,1,2,3,4,5};
auto v = views::counted(x, 5);
VERIFY( ranges::equal(v, (int[]){0,1,2,3,4}) );
using R = decltype(v);
static_assert(ranges::view<R>);
static_assert(ranges::sized_range<R>);
static_assert(ranges::common_range<R>);
static_assert(ranges::random_access_range<R>);
}
void
test02()
{
int x[] = {0,1,2,3,4,5,0,1,2,3,4,5};
test_range<int, forward_iterator_wrapper> rx(x);
auto v = views::counted(rx.begin(), 5);
VERIFY( ranges::equal(v, (int[]){0,1,2,3,4}) );
using R = decltype(v);
static_assert(ranges::view<R>);
static_assert(ranges::sized_range<R>);
static_assert(!ranges::common_range<R>);
static_assert(!ranges::bidirectional_range<R>);
}
int
main()
{
test01();
test02();
}

View File

@ -0,0 +1,107 @@
// 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 <testsuite_hooks.h>
#include <testsuite_iterators.h>
using __gnu_test::test_range;
using __gnu_test::bidirectional_iterator_wrapper;
namespace ranges = std::ranges;
namespace views = ranges::views;
void
test01()
{
int x[] = {1,2,3,4,5};
auto v = x | views::drop(3);
using R = decltype(v);
static_assert(ranges::view<R>);
static_assert(ranges::sized_range<R>);
static_assert(ranges::random_access_range<R>);
VERIFY( ranges::equal(v, (int[]){4,5}) );
}
void
test02()
{
int x[] = {1,2,3,4,5};
auto t = views::drop(3) | views::reverse;
auto v = x | t;
using R = decltype(v);
static_assert(ranges::view<R>);
static_assert(ranges::sized_range<R>);
static_assert(ranges::random_access_range<R>);
VERIFY( ranges::equal(v, (int[]){5,4}) );
}
void
test03()
{
int x[] = {1,2,3,4,5};
test_range<int, bidirectional_iterator_wrapper> rx(x);
auto v = rx | views::drop(3);
using R = decltype(v);
static_assert(ranges::view<R>);
static_assert(!ranges::sized_range<R>);
static_assert(ranges::bidirectional_range<R>);
VERIFY( ranges::equal(v, (int[]){4,5}) );
}
void
test04()
{
auto v = views::iota(0) | views::drop(10);
using R = decltype(v);
static_assert(ranges::view<R>);
static_assert(!ranges::sized_range<R>);
VERIFY( ranges::equal(v | views::take(3), (int[]){10,11,12}) );
}
void
test05()
{
int x[] = {1,2,3};
auto r = ranges::subrange(x, x+1);
auto v = views::drop(r, 2);
VERIFY( ranges::begin(v) == x+1 );
VERIFY( ranges::size(v) == 0 );
}
void
test06()
{
int x[] = {1,2,3};
VERIFY( ranges::empty(x | views::drop(10)) );
}
int
main()
{
test01();
test02();
test03();
test04();
test05();
test06();
}

View File

@ -0,0 +1,63 @@
// 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 <testsuite_hooks.h>
#include <testsuite_iterators.h>
using __gnu_test::test_range;
using __gnu_test::bidirectional_iterator_wrapper;
namespace ranges = std::ranges;
namespace views = std::ranges::views;
void
test01()
{
auto p = [] (int i) { return i != 16; };
auto v = views::iota(10) | views::drop_while(p);
VERIFY( ranges::equal(v | views::take(5), (int[]){16,17,18,19,20}) );
using R = decltype(v);
static_assert(ranges::view<R>);
static_assert(!ranges::common_range<R>);
static_assert(ranges::random_access_range<R>);
}
void
test02()
{
int x[] = {1,2,3,4,5};
test_range<int, bidirectional_iterator_wrapper> rx(x);
auto v = rx | views::drop_while([] (int i) { return i<4; });
VERIFY( ranges::equal(v, (int[]){4,5}) );
using R = decltype(v);
static_assert(ranges::view<R>);
static_assert(!ranges::common_range<R>);
static_assert(ranges::bidirectional_range<R>);
}
int
main()
{
test01();
test02();
}

View File

@ -0,0 +1,52 @@
// 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 <testsuite_hooks.h>
#include <testsuite_iterators.h>
#include <tuple>
namespace ranges = std::ranges;
namespace views = ranges::views;
void
test01()
{
std::tuple<int, int> x[] = {{1,2},{3,4},{5,6}};
auto v0 = x | views::elements<0>;
VERIFY( ranges::equal(v0, (int[]){1,3,5}) );
VERIFY( ranges::equal(v0, x | views::keys) );
VERIFY( ranges::size(v0) == 3 );
using R0 = decltype(v0);
static_assert(ranges::random_access_range<R0>);
static_assert(ranges::sized_range<R0>);
auto v1 = x | views::reverse | views::elements<1> | views::reverse;
VERIFY( ranges::equal(v1, (int[]){2,4,6}) );
VERIFY( ranges::equal(v1, x | views::values) );
}
int
main()
{
test01();
}

View File

@ -0,0 +1,97 @@
// 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 <testsuite_hooks.h>
#include <testsuite_iterators.h>
using __gnu_test::test_range;
using __gnu_test::bidirectional_iterator_wrapper;
namespace ranges = std::ranges;
namespace views = std::ranges::views;
void
test01()
{
int x[] = {1,2,3,4,5,6};
auto is_odd = [] (int i) { return i%2==1; };
auto v = x | views::filter(is_odd);
using R = decltype(v);
static_assert(std::same_as<int&, decltype(*v.begin())>);
static_assert(ranges::view<R>);
static_assert(ranges::input_range<R>);
static_assert(ranges::common_range<R>);
static_assert(!ranges::sized_range<R>);
static_assert(ranges::bidirectional_range<R>);
static_assert(!ranges::random_access_range<R>);
static_assert(ranges::range<ranges::all_view<R>>);
VERIFY( ranges::equal(v, (int[]){1,3,5}) );
VERIFY( ranges::equal(v | views::reverse, (int[]){5,3,1}) );
}
void
test02()
{
int x[] = {1,2,3,4,5,6};
auto f = [flag=false] (int) mutable { return flag = !flag; };
auto v = views::filter(f)(x);
using R = decltype(v);
static_assert(std::same_as<int&, decltype(*v.begin())>);
static_assert(ranges::range<R>);
static_assert(std::copyable<R>);
static_assert(!ranges::view<const R>);
VERIFY( ranges::equal(v, (int[]){1,3,5}) );
}
struct X
{
int i, j;
};
void
test03()
{
X x[] = {{1,3}, {2,5}, {3,7}, {4,9}};
test_range<X, bidirectional_iterator_wrapper> rx(x);
auto v = rx | views::filter([] (auto&& p) { return p.i%2==0; });
int sum = 0;
for (auto i = v.begin(); i != v.end(); ++i)
sum += i->j;
VERIFY( sum == 14 );
}
void
test04()
{
auto yes = [] (int) { return true; };
VERIFY( ranges::equal(views::iota(0) | views::filter(yes) | views::take(1),
(int[]){0}) );
}
int
main()
{
test01();
test02();
test03();
test04();
}

View File

@ -0,0 +1,112 @@
// 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 <string>
#include <string_view>
#include <vector>
#include <testsuite_hooks.h>
#include <testsuite_iterators.h>
namespace ranges = std::ranges;
namespace views = std::ranges::views;
void
test01()
{
using namespace std::literals;
std::string_view cs[] = {"the", "quick", "brown", "fox"};
auto v = cs | views::join;
VERIFY( ranges::equal(v, "thequickbrownfox"sv) );
using R = decltype(v);
static_assert(ranges::bidirectional_range<R>);
static_assert(ranges::bidirectional_range<const R>);
static_assert(ranges::common_range<R>);
static_assert(ranges::common_range<const R>);
}
void
test02()
{
auto v = (views::iota(0,4)
| views::transform([] (int i) { return views::iota(0,i); })
| views::join);
VERIFY( ranges::equal(v, (int[]){0,0,1,0,1,2}) );
using R = decltype(v);
static_assert(ranges::input_range<R>);
static_assert(!ranges::range<const R>);
static_assert(!ranges::forward_range<R>);
static_assert(!ranges::common_range<const R>);
}
void
test03()
{
auto v = (views::iota(0,4)
| views::transform([] (int i) { return views::iota(0,i); })
| views::filter([] (auto) { return true; })
| views::join);
VERIFY( ranges::equal(v, (int[]){0,0,1,0,1,2}) );
using R = decltype(v);
static_assert(ranges::input_range<R>);
static_assert(!ranges::range<const R>);
static_assert(!ranges::forward_range<R>);
static_assert(!ranges::common_range<const R>);
}
void
test04()
{
auto v = (views::iota(0,4)
| views::transform([] (int i) { return views::iota(0,i); }));
auto v2 = ranges::ref_view{v};
VERIFY( ranges::equal(v2 | views::join, (int[]){0,0,1,0,1,2}) );
using R = decltype(v2);
static_assert(ranges::random_access_range<R>);
static_assert(ranges::range<const R>);
static_assert(ranges::common_range<const R>);
static_assert(ranges::random_access_range<ranges::range_reference_t<R>>);
static_assert(!std::is_reference_v<ranges::range_reference_t<R>>);
}
void
test05()
{
using namespace std::literals;
std::vector<std::string> x = {"the", " ", "quick", " ", "brown", " ", "fox"};
auto v = x | views::join | views::split(' ');
auto i = v.begin();
VERIFY( ranges::equal(*i++, "the"sv) );
VERIFY( ranges::equal(*i++, "quick"sv) );
VERIFY( ranges::equal(*i++, "brown"sv) );
VERIFY( ranges::equal(*i++, "fox"sv) );
VERIFY( i == v.end() );
}
int
main()
{
test01();
test02();
test03();
test04();
test05();
}

View File

@ -0,0 +1,86 @@
// 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 <testsuite_hooks.h>
#include <testsuite_iterators.h>
using __gnu_test::test_range;
using __gnu_test::bidirectional_iterator_wrapper;
namespace ranges = std::ranges;
namespace views = ranges::views;
void
test01()
{
int x[] = {1,2,3,4,5};
auto v = x | views::reverse;
VERIFY( ranges::equal(v, (int[]){5,4,3,2,1}) );
VERIFY( ranges::equal(v | views::reverse, x) );
static_assert(ranges::view<decltype(v)>);
static_assert(ranges::sized_range<decltype(v)>);
static_assert(ranges::common_range<decltype(v)>);
static_assert(ranges::random_access_range<decltype(v)>);
}
void
test02()
{
int x[] = {1,2,3,4,5};
test_range<int, bidirectional_iterator_wrapper> rx(x);
auto v = views::reverse(rx);
VERIFY( ranges::equal(v, (int[]){5,4,3,2,1}) );
VERIFY( ranges::equal(v | views::reverse, rx) );
static_assert(ranges::view<decltype(v)>);
static_assert(!ranges::sized_range<decltype(v)>);
static_assert(ranges::common_range<decltype(v)>);
static_assert(!ranges::random_access_range<decltype(v)>);
static_assert(ranges::bidirectional_range<decltype(v)>);
}
void
test03()
{
int x[] = {1,7,3,6,5,2,4,8};
auto is_even = [] (int i) { return i%2==0; };
int sum = 0;
for (auto i : x | views::reverse | views::filter(is_even))
sum += i;
VERIFY( sum == 20 );
}
void
test04()
{
int x[] = {1,2,3,4,5};
VERIFY( ranges::equal(x | views::reverse | (views::reverse | views::reverse),
(int[]){5,4,3,2,1}) );
}
int
main()
{
test01();
test02();
test03();
test04();
}

View File

@ -0,0 +1,82 @@
// 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 <string>
#include <string_view>
#include <testsuite_hooks.h>
#include <testsuite_iterators.h>
using __gnu_test::test_range;
using __gnu_test::forward_iterator_wrapper;
namespace ranges = std::ranges;
namespace views = std::ranges::views;
using namespace std::literals;
void
test01()
{
auto x = "the quick brown fox"sv;
auto p = std::string{" "};
auto v = x | views::split(p);
auto i = v.begin();
VERIFY( ranges::equal(*i++, "the"sv) );
VERIFY( ranges::equal(*i++, "quick"sv) );
VERIFY( ranges::equal(*i++, "brown"sv) );
VERIFY( ranges::equal(*i++, "fox"sv) );
VERIFY( i == v.end() );
}
void
test02()
{
auto x = "the quick brown fox"sv;
auto v = x | views::split(' ');
auto i = v.begin();
VERIFY( ranges::equal(*i++, "the"sv) );
VERIFY( ranges::equal(*i++, "quick"sv) );
VERIFY( ranges::equal(*i++, "brown"sv) );
VERIFY( ranges::equal(*i++, "fox"sv) );
VERIFY( i == v.end() );
}
void
test03()
{
char x[] = "the quick brown fox";
test_range<char, forward_iterator_wrapper> rx(x);
auto v = rx | views::split(' ');
auto i = v.begin();
VERIFY( ranges::equal(*i++, "the"sv) );
VERIFY( ranges::equal(*i++, "quick"sv) );
VERIFY( ranges::equal(*i++, "brown"sv) );
VERIFY( ranges::equal(*i++, "fox"sv) );
VERIFY( i == v.end() );
}
int
main()
{
test01();
test02();
}

View File

@ -0,0 +1,95 @@
// 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 <testsuite_hooks.h>
#include <testsuite_iterators.h>
using __gnu_test::test_range;
using __gnu_test::bidirectional_iterator_wrapper;
namespace ranges = std::ranges;
namespace views = ranges::views;
void
test01()
{
auto v = views::iota(0) | views::take(5);
static_assert(ranges::view<decltype(v)>);
static_assert(!ranges::sized_range<decltype(v)>);
static_assert(!ranges::common_range<decltype(v)>);
static_assert(ranges::random_access_range<decltype(v)>);
static_assert(!ranges::contiguous_range<decltype(v)>);
static_assert(ranges::range<const decltype(v)>);
VERIFY( ranges::equal(v, (int[]){0,1,2,3,4}) );
}
void
test02()
{
auto v = views::take(views::iota(0, 20), 5);
static_assert(ranges::view<decltype(v)>);
static_assert(ranges::sized_range<decltype(v)>);
static_assert(ranges::common_range<decltype(v)>);
static_assert(ranges::random_access_range<decltype(v)>);
static_assert(!ranges::contiguous_range<decltype(v)>);
static_assert(ranges::range<const decltype(v)>);
VERIFY( ranges::equal(v, (int[]){0,1,2,3,4}) );
}
void
test03()
{
int x[] = {0,1,2,3,4,5};
auto is_odd = [] (int i) { return i%2 == 1; };
auto v = x | views::filter(is_odd) | views::take(3);
ranges::begin(v);
using R = decltype(v);
static_assert(ranges::view<R>);
static_assert(!ranges::sized_range<R>);
static_assert(!ranges::common_range<R>);
static_assert(ranges::forward_range<R>);
static_assert(!ranges::random_access_range<R>);
static_assert(!ranges::range<const R>);
VERIFY( ranges::equal(v, (int[]){1,3,5}) );
}
void
test04()
{
int x[] = {1,2,3,4,5};
test_range<int, bidirectional_iterator_wrapper> rx(x);
auto v = ranges::take_view{rx, 3};
using R = decltype(v);
static_assert(ranges::view<R>);
static_assert(!ranges::sized_range<R>);
static_assert(ranges::bidirectional_range<R>);
VERIFY( ranges::equal(v | views::take(5), (int[]){1,2,3}) );
}
int
main()
{
test01();
test02();
test03();
test04();
}

View File

@ -0,0 +1,62 @@
// 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 <testsuite_hooks.h>
#include <testsuite_iterators.h>
using __gnu_test::test_range;
using __gnu_test::forward_iterator_wrapper;
namespace ranges = std::ranges;
namespace views = std::ranges::views;
void
test01()
{
auto p = [] (int i) { return i != 16; };
auto v = views::iota(10) | views::take_while(p);
VERIFY( ranges::equal(v, (int[]){10,11,12,13,14,15}) );
using R = decltype(v);
static_assert(ranges::view<R>);
static_assert(!ranges::common_range<R>);
static_assert(ranges::random_access_range<R>);
}
void
test02()
{
int x[] = {1,2,3,4,5};
test_range<int, forward_iterator_wrapper> rx(x);
auto v = rx | views::take_while([] (int i) { return i<4; });
VERIFY( ranges::equal(v, (int[]){1,2,3}) );
using R = decltype(v);
static_assert(ranges::view<R>);
static_assert(!ranges::common_range<R>);
static_assert(ranges::forward_range<R>);
}
int
main()
{
test01();
test02();
}

View File

@ -0,0 +1,86 @@
// 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 <testsuite_hooks.h>
#include <testsuite_iterators.h>
using __gnu_test::test_range;
using __gnu_test::random_access_iterator_wrapper;
namespace ranges = std::ranges;
namespace views = std::ranges::views;
void
test01()
{
int x[] = {1,2,3,4,5};
auto is_odd = [] (int i) { return i%2==1; };
auto v = x | views::transform(is_odd);
VERIFY( ranges::equal(v, (int[]){1,0,1,0,1}) );
using R = decltype(v);
static_assert(std::same_as<bool, decltype(*ranges::begin(v))>);
static_assert(ranges::view<R>);
static_assert(ranges::sized_range<R>);
static_assert(ranges::random_access_range<R>);
}
struct X
{
int i,j;
};
void
test02()
{
X x[] = {{1,2},{3,4},{5,6},{7,8},{9,10}};
test_range<X, random_access_iterator_wrapper> rx(x);
auto v = rx | views::transform(&X::i);
VERIFY( ranges::size(v) == 5 );
VERIFY( ranges::distance(v.begin(), v.end()) == 5 );
VERIFY( ranges::equal(v, (int[]){1,3,5,7,9}) );
VERIFY( ranges::equal(v | views::reverse, (int[]){9,7,5,3,1}) );
using R = decltype(v);
static_assert(std::same_as<int&, decltype(*ranges::begin(v))>);
static_assert(std::same_as<int, std::iter_value_t<ranges::iterator_t<R>>>);
static_assert(ranges::view<R>);
static_assert(ranges::sized_range<R>);
static_assert(!ranges::common_range<R>);
static_assert(ranges::random_access_range<R>);
}
void
test03()
{
auto id = [] (int i) { return i; };
auto v = views::iota(0) | (views::filter(id)
| views::transform(id)
| views::take(5));
VERIFY( ranges::equal(v, (int[]){1,2,3,4,5}) );
}
int
main()
{
test01();
test02();
test03();
}