| 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 | |