1 /*
2  * Copyright (c) 2024 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 META_BASE_TYPE_TRAITS_H
17 #define META_BASE_TYPE_TRAITS_H
18 
19 #include <base/containers/type_traits.h>
20 
21 #include <meta/base/namespace.h>
22 
23 META_BEGIN_NAMESPACE()
24 
25 template<typename... Types>
26 struct TypeList {};
27 
28 template<bool B>
29 struct BoolWrap {
30     constexpr static bool value = B; // NOLINT(readability-identifier-naming)
31 };
32 
33 // same concept as https://en.cppreference.com/w/cpp/experimental/is_detected but simplified for our needs
34 template<typename Void, template<class...> class Op, typename... Args>
35 struct IsDetected {
36     static constexpr bool value = false; // NOLINT(readability-identifier-naming)
37     using type = BoolWrap<false>;
38 };
39 
40 template<template<class...> class Op, typename... Args>
41 struct IsDetected<decltype(BASE_NS::declval<Op<Args...>>(), void()), Op, Args...> {
42     static constexpr bool value = true; // NOLINT(readability-identifier-naming)
43     using type = Op<Args...>;
44 };
45 
46 template<template<class...> class Op, typename... Args>
47 constexpr bool IsDetected_v = IsDetected<void, Op, Args...>::value; // NOLINT(readability-identifier-naming)
48 
49 // NOLINTBEGIN(readability-identifier-naming)
50 template<template<class...> class Op, typename... Args>
51 constexpr bool IsDetectedWithValue_v = IsDetected<void, Op, Args...>::type::value;
52 // NOLINTEND(readability-identifier-naming)
53 
54 template<typename T>
55 using PlainType_t = BASE_NS::remove_const_t<BASE_NS::remove_reference_t<T>>; // NOLINT(readability-identifier-naming)
56 
57 template<size_t... Ints>
58 struct IndexSequence {};
59 
60 template<size_t Size, size_t... Ints>
61 struct MakeIndexSequenceImpl {
62     using type = typename MakeIndexSequenceImpl<Size - 1, Size - 1, Ints...>::type;
63 };
64 
65 template<size_t... Ints>
66 struct MakeIndexSequenceImpl<0, Ints...> {
67     using type = IndexSequence<Ints...>;
68 };
69 
70 template<typename... Args>
71 using MakeIndexSequenceFor = typename MakeIndexSequenceImpl<sizeof...(Args)>::type;
72 
73 template<size_t Size>
74 using MakeIndexSequence = typename MakeIndexSequenceImpl<Size>::type;
75 
76 template<typename Type>
77 struct NonDeduced {
78     using type = Type;
79 };
80 template<typename Type>
81 using NonDeduced_t = typename NonDeduced<Type>::type;
82 
83 template<typename T>
84 constexpr bool is_enum_v = __is_enum(T); // NOLINT(readability-identifier-naming)
85 
86 META_END_NAMESPACE()
87 
88 /*
89     Description:
90         This can turn SFINAE failures into false values, allowing to construct constexpr bool variables
91 
92     Example:
93 
94     template<typename Type>
95     using KinfOfInterfaceCheck = BoolWrap<IsKindOfIInterface_v<typename Type::element_type*>>;
96 
97     template<typename Type>
98     constexpr bool IsInterfacePtr_v = IsKindOfPointer_v<Type> && IsDetectedWithValue_v<KinfOfInterfaceCheck, Type>;
99 
100     this cannot be written directly since Type::element_type fails to compile.
101 
102     Or
103 
104     template<typename Type>
105     using HasMyMember = decltype(BASE_NS::declval<Type>().MyMember());
106 
107     template<typename Type>
108     constexpr bool HasMyMember_v = IsDetected_v<HasMyMember, Type>;
109 */
110 
111 #endif
112