#include <array>
#include <concepts>
#include <tuple>
#include <ranges>
#include <utility>
#include "test_iterators.h"
template <class It>
using Range = std::ranges::subrange<It, sentinel_wrapper<It>>;
template <class V, std::size_t N>
concept HasElementsView = requires { typename std::ranges::elements_view<V, N>; };
static_assert(HasElementsView<Range<std::ranges::subrange<int*>*>, 0>);
static_assert(HasElementsView<Range<std::pair<int, int>*>, 1>);
static_assert(HasElementsView<Range<std::tuple<int, int, int>*>, 2>);
static_assert(HasElementsView<Range<std::array<int, 4>*>, 3>);
static_assert(!std::ranges::view<std::array<std::tuple<int>, 1>>);
static_assert(!HasElementsView<std::array<std::tuple<int>, 1>, 0>);
static_assert(!std::ranges::input_range<Range<cpp20_output_iterator<std::tuple<int>*>>>);
static_assert(!HasElementsView<Range<cpp20_output_iterator<std::tuple<int>*>>, 0>);
static_assert(!HasElementsView<Range<int*>, 1>);
static_assert(!(2 < std::tuple_size_v< std::pair<int, int>>));
static_assert(!HasElementsView<Range<std::pair<int, int>*>, 2>);
struct NonMovable {
NonMovable(int) {}
NonMovable(NonMovable&&) = delete;
};
static_assert(!std::move_constructible<NonMovable>);
using NonMovableGenerator =
decltype(std::views::iota(0, 1) | std::views::transform([](int) {
return std::pair<NonMovable, int>{1, 1};
}));
static_assert(!HasElementsView<NonMovableGenerator, 0>);
static_assert(HasElementsView<NonMovableGenerator, 1>);