//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// <tuple>
// 22.4.3 Concept `tuple-like` [tuple.like]
//
// template<class T>
// concept tuple-like; // exposition only
#include <__tuple/tuple_like.h>
#include <array>
#include <complex>
#include <ranges>
#include <tuple>
#include "test_iterators.h"
// Non-tuple-like type
static_assert(!std::__tuple_like<int>);
// Tuple-like: array
static_assert(std::__tuple_like<std::array<int, 0>>);
static_assert(std::__tuple_like<std::array<int, 1>>);
static_assert(std::__tuple_like<std::array<int, 2>>);
static_assert(std::__tuple_like<std::array<int, 2728>>);
// Tuple-like: complex
#if _LIBCPP_STD_VER >= 26
static_assert(std::__tuple_like<std::complex<float>>);
static_assert(std::__tuple_like<std::complex<double>>);
static_assert(std::__tuple_like<std::complex<long double>>);
#endif
// Tuple-like: pair
static_assert(std::__tuple_like<std::pair<int, float>>);
// Tuple-like: tuple
static_assert(std::__tuple_like<std::tuple<int>>);
static_assert(std::__tuple_like<std::tuple<int, float>>);
static_assert(std::__tuple_like<std::tuple<int, float, double>>);
// Support for <ranges>
using FI = forward_iterator<int*>;
static_assert(std::__tuple_like<std::ranges::subrange<FI, FI, std::ranges::subrange_kind::sized>>);
static_assert(std::__tuple_like<std::ranges::subrange<FI, FI, std::ranges::subrange_kind::unsized>>);
static_assert(std::__tuple_like<std::ranges::subrange<int*, int*, std::ranges::subrange_kind::sized>>);
static_assert(std::__tuple_like<std::ranges::subrange<int*, std::nullptr_t, std::ranges::subrange_kind::unsized>>);
template <typename Iter>
void test_subrange_sized() {
static_assert(std::__tuple_like<std::ranges::subrange<Iter, Iter, std::ranges::subrange_kind::sized>>);
}
template <typename Iter>
void test_subrange_unsized() {
static_assert(std::__tuple_like<std::ranges::subrange<Iter, Iter, std::ranges::subrange_kind::unsized>>);
}
void test() {
test_subrange_sized<forward_iterator<int*>>();
test_subrange_sized<bidirectional_iterator<int*>>();
test_subrange_sized<random_access_iterator<int*>>();
test_subrange_sized<contiguous_iterator<int*>>();
test_subrange_sized<int*>();
test_subrange_sized<forward_iterator<int const*>>();
test_subrange_sized<bidirectional_iterator<int const*>>();
test_subrange_sized<random_access_iterator<int const*>>();
test_subrange_sized<contiguous_iterator<int const*>>();
test_subrange_sized<int const*>();
test_subrange_unsized<forward_iterator<int*>>();
test_subrange_unsized<bidirectional_iterator<int*>>();
static_assert(std::__tuple_like<std::ranges::subrange<int*, std::nullptr_t, std::ranges::subrange_kind::unsized>>);
test_subrange_unsized<forward_iterator<int const*>>();
test_subrange_unsized<bidirectional_iterator<int const*>>();
static_assert(
std::__tuple_like<std::ranges::subrange<const int*, std::nullptr_t, std::ranges::subrange_kind::unsized>>);
}