1// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP___ITERATOR_READABLE_TRAITS_H
11#define _LIBCPP___ITERATOR_READABLE_TRAITS_H
12
13#include <__concepts/same_as.h>
14#include <__config>
15#include <__type_traits/conditional.h>
16#include <__type_traits/is_array.h>
17#include <__type_traits/is_object.h>
18#include <__type_traits/is_primary_template.h>
19#include <__type_traits/remove_cv.h>
20#include <__type_traits/remove_cvref.h>
21#include <__type_traits/remove_extent.h>
22
23#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
24#  pragma GCC system_header
25#endif
26
27_LIBCPP_BEGIN_NAMESPACE_STD
28
29#if _LIBCPP_STD_VER >= 20
30
31// [readable.traits]
32template <class>
33struct __cond_value_type {};
34
35template <class _Tp>
36  requires is_object_v<_Tp>
37struct __cond_value_type<_Tp> {
38  using value_type = remove_cv_t<_Tp>;
39};
40
41template <class _Tp>
42concept __has_member_value_type = requires { typename _Tp::value_type; };
43
44template <class _Tp>
45concept __has_member_element_type = requires { typename _Tp::element_type; };
46
47template <class>
48struct indirectly_readable_traits {};
49
50template <class _Ip>
51  requires is_array_v<_Ip>
52struct indirectly_readable_traits<_Ip> {
53  using value_type = remove_cv_t<remove_extent_t<_Ip>>;
54};
55
56template <class _Ip>
57struct indirectly_readable_traits<const _Ip> : indirectly_readable_traits<_Ip> {};
58
59template <class _Tp>
60struct indirectly_readable_traits<_Tp*> : __cond_value_type<_Tp> {};
61
62template <__has_member_value_type _Tp>
63struct indirectly_readable_traits<_Tp> : __cond_value_type<typename _Tp::value_type> {};
64
65template <__has_member_element_type _Tp>
66struct indirectly_readable_traits<_Tp> : __cond_value_type<typename _Tp::element_type> {};
67
68template <__has_member_value_type _Tp>
69  requires __has_member_element_type<_Tp>
70struct indirectly_readable_traits<_Tp> {};
71
72template <__has_member_value_type _Tp>
73  requires __has_member_element_type<_Tp> &&
74           same_as<remove_cv_t<typename _Tp::element_type>, remove_cv_t<typename _Tp::value_type>>
75struct indirectly_readable_traits<_Tp> : __cond_value_type<typename _Tp::value_type> {};
76
77#endif // _LIBCPP_STD_VER >= 20
78
79_LIBCPP_END_NAMESPACE_STD
80
81#endif // _LIBCPP___ITERATOR_READABLE_TRAITS_H
82