xref: /llvm-project/libcxx/test/std/ranges/range.adaptors/range.elements/range.concept.compile.pass.cpp (revision 1679b27959bbe21b713725017b1cf36ac66dfadc)
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 {
NonMovableNonMovable63   NonMovable(int) {}
64   NonMovable(NonMovable&&) = delete;
65 };
66 static_assert(!std::move_constructible<NonMovable>);
67 
68 using NonMovableGenerator =
__anonac528cf60102(int) 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