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