• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Tint Authors.
2 //
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 #ifndef SRC_TRAITS_H_
16 #define SRC_TRAITS_H_
17 
18 #include <tuple>
19 
20 namespace tint {
21 namespace traits {
22 
23 /// Convience type definition for std::decay<T>::type
24 template <typename T>
25 using Decay = typename std::decay<T>::type;
26 
27 /// NthTypeOf returns the `N`th type in `Types`
28 template <int N, typename... Types>
29 using NthTypeOf = typename std::tuple_element<N, std::tuple<Types...>>::type;
30 
31 /// Signature describes the signature of a function.
32 template <typename RETURN, typename... PARAMETERS>
33 struct Signature {
34   /// The return type of the function signature
35   using ret = RETURN;
36   /// The parameters of the function signature held in a std::tuple
37   using parameters = std::tuple<PARAMETERS...>;
38   /// The type of the Nth parameter of function signature
39   template <std::size_t N>
40   using parameter = NthTypeOf<N, PARAMETERS...>;
41   /// The total number of parameters
42   static constexpr std::size_t parameter_count = sizeof...(PARAMETERS);
43 };
44 
45 /// SignatureOf is a traits helper that infers the signature of the function,
46 /// method, static method, lambda, or function-like object `F`.
47 template <typename F>
48 struct SignatureOf {
49   /// The signature of the function-like object `F`
50   using type = typename SignatureOf<decltype(&F::operator())>::type;
51 };
52 
53 /// SignatureOf specialization for a regular function or static method.
54 template <typename R, typename... ARGS>
55 struct SignatureOf<R (*)(ARGS...)> {
56   /// The signature of the function-like object `F`
57   using type = Signature<typename std::decay<R>::type,
58                          typename std::decay<ARGS>::type...>;
59 };
60 
61 /// SignatureOf specialization for a non-static method.
62 template <typename R, typename C, typename... ARGS>
63 struct SignatureOf<R (C::*)(ARGS...)> {
64   /// The signature of the function-like object `F`
65   using type = Signature<typename std::decay<R>::type,
66                          typename std::decay<ARGS>::type...>;
67 };
68 
69 /// SignatureOf specialization for a non-static, const method.
70 template <typename R, typename C, typename... ARGS>
71 struct SignatureOf<R (C::*)(ARGS...) const> {
72   /// The signature of the function-like object `F`
73   using type = Signature<typename std::decay<R>::type,
74                          typename std::decay<ARGS>::type...>;
75 };
76 
77 /// SignatureOfT is an alias to `typename SignatureOf<F>::type`.
78 template <typename F>
79 using SignatureOfT = typename SignatureOf<F>::type;
80 
81 /// ParameterType is an alias to `typename SignatureOf<F>::type::parameter<N>`.
82 template <typename F, std::size_t N>
83 using ParameterType = typename SignatureOfT<F>::template parameter<N>;
84 
85 /// ReturnType is an alias to `typename SignatureOf<F>::type::ret`.
86 template <typename F>
87 using ReturnType = typename SignatureOfT<F>::ret;
88 
89 /// `IsTypeOrDerived<T, BASE>::value` is true iff `T` is of type `BASE`, or
90 /// derives from `BASE`.
91 template <typename T, typename BASE>
92 using IsTypeOrDerived =
93     std::integral_constant<bool,
94                            std::is_base_of<BASE, Decay<T>>::value ||
95                                std::is_same<BASE, Decay<T>>::value>;
96 
97 /// If `CONDITION` is true then EnableIf resolves to type T, otherwise an
98 /// invalid type.
99 template <bool CONDITION, typename T>
100 using EnableIf = typename std::enable_if<CONDITION, T>::type;
101 
102 /// If `T` is of type `BASE`, or derives from `BASE`, then EnableIfIsType
103 /// resolves to type `T`, otherwise an invalid type.
104 template <typename T, typename BASE>
105 using EnableIfIsType = EnableIf<IsTypeOrDerived<T, BASE>::value, T>;
106 
107 /// If `T` is not of type `BASE`, or does not derive from `BASE`, then
108 /// EnableIfIsNotType resolves to type `T`, otherwise an invalid type.
109 template <typename T, typename BASE>
110 using EnableIfIsNotType = EnableIf<!IsTypeOrDerived<T, BASE>::value, T>;
111 
112 }  // namespace traits
113 }  // namespace tint
114 
115 #endif  // SRC_TRAITS_H_
116