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
35template <class It>
36using Range = std::ranges::subrange<It, sentinel_wrapper<It>>;
37
38template <class V, std::size_t N>
39concept HasElementsView = requires { typename std::ranges::elements_view<V, N>; };
40
41static_assert(HasElementsView<Range<std::ranges::subrange<int*>*>, 0>);
42static_assert(HasElementsView<Range<std::pair<int, int>*>, 1>);
43static_assert(HasElementsView<Range<std::tuple<int, int, int>*>, 2>);
44static_assert(HasElementsView<Range<std::array<int, 4>*>, 3>);
45
46// !view<V>
47static_assert(!std::ranges::view<std::array<std::tuple<int>, 1>>);
48static_assert(!HasElementsView<std::array<std::tuple<int>, 1>, 0>);
49
50// !input_range
51static_assert(!std::ranges::input_range<Range<cpp20_output_iterator<std::tuple<int>*>>>);
52static_assert(!HasElementsView<Range<cpp20_output_iterator<std::tuple<int>*>>, 0>);
53
54// !tuple-like
55static_assert(!HasElementsView<Range<int*>, 1>);
56
57// !(N < tuple_size_v<T>)
58static_assert(!(2 < std::tuple_size_v< std::pair<int, int>>));
59static_assert(!HasElementsView<Range<std::pair<int, int>*>, 2>);
60
61// ! (is_reference_v<T> || move_constructible<tuple_element_t<N, T>>)
62struct NonMovable {
63 NonMovable(int) {}
64 NonMovable(NonMovable&&) = delete;
65};
66static_assert(!std::move_constructible<NonMovable>);
67
68using NonMovableGenerator =
69 decltype(std::views::iota(0, 1) | std::views::transform([](int) {
70 return std::pair<NonMovable, int>{1, 1};
71 }));
72
73static_assert(!HasElementsView<NonMovableGenerator, 0>);
74static_assert(HasElementsView<NonMovableGenerator, 1>);
75

source code of libcxx/test/std/ranges/range.adaptors/range.elements/range.concept.compile.pass.cpp