1 | //===----------------------------------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | // UNSUPPORTED: c++03, c++11, c++14, c++17 |
10 | |
11 | // concept checking |
12 | // |
13 | // template<class T, size_t N> |
14 | // concept has-tuple-element = |
15 | // tuple-like<T> && N < tuple_size_v<T>; |
16 | // |
17 | // template<class T, size_t N> |
18 | // concept returnable-element = |
19 | // is_reference_v<T> || move_constructible<tuple_element_t<N, T>>; |
20 | // |
21 | // template<input_range V, size_t N> |
22 | // requires view<V> && has-tuple-element<range_value_t<V>, N> && |
23 | // has-tuple-element<remove_reference_t<range_reference_t<V>>, N> && |
24 | // returnable-element<range_reference_t<V>, N> |
25 | // class elements_view; |
26 | |
27 | #include <array> |
28 | #include <concepts> |
29 | #include <tuple> |
30 | #include <ranges> |
31 | #include <utility> |
32 | |
33 | #include "test_iterators.h" |
34 | |
35 | template <class It> |
36 | using Range = std::ranges::subrange<It, sentinel_wrapper<It>>; |
37 | |
38 | template <class V, std::size_t N> |
39 | concept HasElementsView = requires { typename std::ranges::elements_view<V, N>; }; |
40 | |
41 | static_assert(HasElementsView<Range<std::ranges::subrange<int*>*>, 0>); |
42 | static_assert(HasElementsView<Range<std::pair<int, int>*>, 1>); |
43 | static_assert(HasElementsView<Range<std::tuple<int, int, int>*>, 2>); |
44 | static_assert(HasElementsView<Range<std::array<int, 4>*>, 3>); |
45 | |
46 | // !view<V> |
47 | static_assert(!std::ranges::view<std::array<std::tuple<int>, 1>>); |
48 | static_assert(!HasElementsView<std::array<std::tuple<int>, 1>, 0>); |
49 | |
50 | // !input_range |
51 | static_assert(!std::ranges::input_range<Range<cpp20_output_iterator<std::tuple<int>*>>>); |
52 | static_assert(!HasElementsView<Range<cpp20_output_iterator<std::tuple<int>*>>, 0>); |
53 | |
54 | // !tuple-like |
55 | static_assert(!HasElementsView<Range<int*>, 1>); |
56 | |
57 | // !(N < tuple_size_v<T>) |
58 | static_assert(!(2 < std::tuple_size_v< std::pair<int, int>>)); |
59 | static_assert(!HasElementsView<Range<std::pair<int, int>*>, 2>); |
60 | |
61 | // ! (is_reference_v<T> || move_constructible<tuple_element_t<N, T>>) |
62 | struct NonMovable { |
63 | NonMovable(int) {} |
64 | NonMovable(NonMovable&&) = delete; |
65 | }; |
66 | static_assert(!std::move_constructible<NonMovable>); |
67 | |
68 | using NonMovableGenerator = |
69 | decltype(std::views::iota(0, 1) | std::views::transform([](int) { |
70 | return std::pair<NonMovable, int>{1, 1}; |
71 | })); |
72 | |
73 | static_assert(!HasElementsView<NonMovableGenerator, 0>); |
74 | static_assert(HasElementsView<NonMovableGenerator, 1>); |
75 | |