1/**
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBPANDABASE_CONCEPTS_H
17#define LIBPANDABASE_CONCEPTS_H
18
19#include <iterator>
20
21namespace panda {
22
23/// Iterable concept
24
25template <typename T, typename = void>
26struct is_iterable : public std::false_type {};  // NOLINT(readability-identifier-naming)
27
28template <typename T>
29struct is_iterable<  // NOLINT(readability-identifier-naming)
30    T, std::void_t<typename T::iterator, decltype(std::declval<T>().begin()), decltype(std::declval<T>().end())>>
31    : public std::true_type {};
32
33template <typename T>
34// NOLINTNEXTLINE(readability-identifier-naming, misc-definitions-in-headers)
35constexpr bool is_iterable_v = is_iterable<T>::value;
36
37/// Random access iterable concept
38
39template <typename T>
40struct is_random_access_iterable  // NOLINT(readability-identifier-naming)
41    : public std::bool_constant<is_iterable_v<T> &&
42                                std::is_same_v<typename std::iterator_traits<typename T::iterator>::iterator_category,
43                                               std::random_access_iterator_tag>> {};
44
45template <typename T>
46// NOLINTNEXTLINE(readability-identifier-naming, misc-definitions-in-headers)
47constexpr bool is_random_access_iterable_v = is_random_access_iterable<T>::value;
48
49/// Forward iterable concept
50
51template <typename T>
52struct is_forward_iterable  // NOLINT(readability-identifier-naming)
53    : public std::bool_constant<is_iterable_v<T> &&
54                                std::is_same_v<typename std::iterator_traits<typename T::iterator>::iterator_category,
55                                               std::forward_iterator_tag>> {};
56
57template <typename T>
58// NOLINTNEXTLINE(readability-identifier-naming, misc-definitions-in-headers)
59constexpr bool is_forward_iterable_v = is_forward_iterable<T>::value;
60
61/// Vectorable concept
62
63template <class V, typename = void>
64struct is_vectorable : public std::false_type {};  // NOLINT(readability-identifier-naming)
65
66template <class V>
67struct is_vectorable<  // NOLINT(readability-identifier-naming)
68    V, std::void_t<typename V::value_type, typename V::allocator_type, decltype(std::declval<V>().size()),
69                   decltype(std::declval<V>().data())>> : public std::bool_constant<is_random_access_iterable_v<V>> {};
70
71template <class V>
72// NOLINTNEXTLINE(readability-identifier-naming, misc-definitions-in-headers)
73constexpr bool is_vectorable_v = is_vectorable<V>::value;
74
75/// Stringable concept
76
77template <class S, typename = void>
78struct is_stringable : public std::false_type {};  // NOLINT(readability-identifier-naming)
79
80template <class S>
81struct is_stringable<  // NOLINT(readability-identifier-naming)
82    S, std::void_t<typename S::value_type, typename S::allocator_type, typename S::traits_type,
83                   decltype(std::declval<S>().length()), decltype(std::declval<S>().data())>>
84    : public std::bool_constant<is_random_access_iterable_v<S>> {};
85
86template <class S>
87// NOLINTNEXTLINE(readability-identifier-naming, misc-definitions-in-headers)
88constexpr bool is_stringable_v = is_stringable<S>::value;
89
90/// Hash mappable concept
91
92template <class HM, typename = void>
93struct is_hash_mappable : public std::false_type {};  // NOLINT(readability-identifier-naming)
94
95template <class HM>
96struct is_hash_mappable<  // NOLINT(readability-identifier-naming)
97    HM, std::void_t<typename HM::key_type, typename HM::mapped_type, typename HM::value_type, typename HM::hasher,
98                    typename HM::key_equal, typename HM::allocator_type, decltype(std::declval<HM>().size())>>
99    : public std::bool_constant<is_forward_iterable_v<HM>> {};
100
101template <class HM>
102// NOLINTNEXTLINE(readability-identifier-naming, misc-definitions-in-headers)
103constexpr bool is_hash_mappable_v = is_hash_mappable<HM>::value;
104
105/**
106 *  Added in C++20
107 */
108
109/// Checks whether T is an array type of unknown bound
110
111template <class T>
112// NOLINTNEXTLINE(readability-identifier-naming)
113struct is_unbounded_array : public std::false_type {};
114
115template <class T>
116// NOLINTNEXTLINE(readability-identifier-naming, modernize-avoid-c-arrays)
117struct is_unbounded_array<T[]> : public std::true_type {};
118
119template <class T>
120// NOLINTNEXTLINE(readability-identifier-naming, misc-definitions-in-headers)
121constexpr bool is_unbounded_array_v = is_unbounded_array<T>::value;
122
123/// Checks whether T is an array type of known bound
124
125template <class T>
126// NOLINTNEXTLINE(readability-identifier-naming)
127struct is_bounded_array : public std::false_type {};
128
129template <class T, size_t N>
130// NOLINTNEXTLINE(readability-identifier-naming, modernize-avoid-c-arrays)
131struct is_bounded_array<T[N]> : public std::true_type {};
132
133template <class T>
134// NOLINTNEXTLINE(readability-identifier-naming, misc-definitions-in-headers)
135constexpr bool is_bounded_array_v = is_bounded_array<T>::value;
136
137}  // namespace panda
138
139#endif  // LIBPANDABASE_CONCEPTS_H
140