Path: blob/master/Utilities/cmcppdap/include/dap/traits.h
3158 views
// Copyright 2021 Google LLC1//2// Licensed under the Apache License, Version 2.0 (the "License");3// you may not use this file except in compliance with the License.4// You may obtain a copy of the License at5//6// https://www.apache.org/licenses/LICENSE-2.07//8// Unless required by applicable law or agreed to in writing, software9// distributed under the License is distributed on an "AS IS" BASIS,10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.11// See the License for the specific language governing permissions and12// limitations under the License.1314#ifndef dap_traits_h15#define dap_traits_h1617#include <tuple>18#include <type_traits>1920namespace dap {21namespace traits {2223// NthTypeOf returns the `N`th type in `Types`24template <int N, typename... Types>25using NthTypeOf = typename std::tuple_element<N, std::tuple<Types...>>::type;2627// `IsTypeOrDerived<BASE, T>::value` is true iff `T` is of type `BASE`, or28// derives from `BASE`.29template <typename BASE, typename T>30using IsTypeOrDerived = std::integral_constant<31bool,32std::is_base_of<BASE, typename std::decay<T>::type>::value ||33std::is_same<BASE, typename std::decay<T>::type>::value>;3435// `EachIsTypeOrDerived<N, BASES, TYPES>::value` is true iff all of the types in36// the std::tuple `TYPES` is of, or derives from the corresponding indexed type37// in the std::tuple `BASES`.38// `N` must be equal to the number of types in both the std::tuple `BASES` and39// `TYPES`.40template <int N, typename BASES, typename TYPES>41struct EachIsTypeOrDerived {42using base = typename std::tuple_element<N - 1, BASES>::type;43using type = typename std::tuple_element<N - 1, TYPES>::type;44using last_matches = IsTypeOrDerived<base, type>;45using others_match = EachIsTypeOrDerived<N - 1, BASES, TYPES>;46static constexpr bool value = last_matches::value && others_match::value;47};4849// EachIsTypeOrDerived specialization for N = 150template <typename BASES, typename TYPES>51struct EachIsTypeOrDerived<1, BASES, TYPES> {52using base = typename std::tuple_element<0, BASES>::type;53using type = typename std::tuple_element<0, TYPES>::type;54static constexpr bool value = IsTypeOrDerived<base, type>::value;55};5657// EachIsTypeOrDerived specialization for N = 058template <typename BASES, typename TYPES>59struct EachIsTypeOrDerived<0, BASES, TYPES> {60static constexpr bool value = true;61};6263// Signature describes the signature of a function.64template <typename RETURN, typename... PARAMETERS>65struct Signature {66// The return type of the function signature67using ret = RETURN;68// The parameters of the function signature held in a std::tuple69using parameters = std::tuple<PARAMETERS...>;70// The type of the Nth parameter of function signature71template <std::size_t N>72using parameter = NthTypeOf<N, PARAMETERS...>;73// The total number of parameters74static constexpr std::size_t parameter_count = sizeof...(PARAMETERS);75};7677// SignatureOf is a traits helper that infers the signature of the function,78// method, static method, lambda, or function-like object `F`.79template <typename F>80struct SignatureOf {81// The signature of the function-like object `F`82using type = typename SignatureOf<decltype(&F::operator())>::type;83};8485// SignatureOf specialization for a regular function or static method.86template <typename R, typename... ARGS>87struct SignatureOf<R (*)(ARGS...)> {88// The signature of the function-like object `F`89using type = Signature<typename std::decay<R>::type,90typename std::decay<ARGS>::type...>;91};9293// SignatureOf specialization for a non-static method.94template <typename R, typename C, typename... ARGS>95struct SignatureOf<R (C::*)(ARGS...)> {96// The signature of the function-like object `F`97using type = Signature<typename std::decay<R>::type,98typename std::decay<ARGS>::type...>;99};100101// SignatureOf specialization for a non-static, const method.102template <typename R, typename C, typename... ARGS>103struct SignatureOf<R (C::*)(ARGS...) const> {104// The signature of the function-like object `F`105using type = Signature<typename std::decay<R>::type,106typename std::decay<ARGS>::type...>;107};108109// SignatureOfT is an alias to `typename SignatureOf<F>::type`.110template <typename F>111using SignatureOfT = typename SignatureOf<F>::type;112113// ParameterType is an alias to `typename SignatureOf<F>::type::parameter<N>`.114template <typename F, std::size_t N>115using ParameterType = typename SignatureOfT<F>::template parameter<N>;116117// `HasSignature<F, S>::value` is true iff the function-like `F` has a matching118// signature to the function-like `S`.119template <typename F, typename S>120using HasSignature = std::integral_constant<121bool,122std::is_same<SignatureOfT<F>, SignatureOfT<S>>::value>;123124// `Min<A, B>::value` resolves to the smaller value of A and B.125template <std::size_t A, std::size_t B>126using Min = std::integral_constant<std::size_t, (A < B ? A : B)>;127128// `CompatibleWith<F, S>::value` is true iff the function-like `F`129// can be called with the argument types of the function-like `S`. Return type130// of the two functions are not considered.131template <typename F, typename S>132using CompatibleWith = std::integral_constant<133bool,134(SignatureOfT<S>::parameter_count == SignatureOfT<F>::parameter_count) &&135EachIsTypeOrDerived<Min<SignatureOfT<S>::parameter_count,136SignatureOfT<F>::parameter_count>::value,137typename SignatureOfT<S>::parameters,138typename SignatureOfT<F>::parameters>::value>;139140// If `CONDITION` is true then EnableIf resolves to type T, otherwise an141// invalid type.142template <bool CONDITION, typename T = void>143using EnableIf = typename std::enable_if<CONDITION, T>::type;144145// If `BASE` is a base of `T` then EnableIfIsType resolves to type `TRUE_TY`,146// otherwise an invalid type.147template <typename BASE, typename T, typename TRUE_TY = void>148using EnableIfIsType = EnableIf<IsTypeOrDerived<BASE, T>::value, TRUE_TY>;149150// If the function-like `F` has a matching signature to the function-like `S`151// then EnableIfHasSignature resolves to type `TRUE_TY`, otherwise an invalid type.152template <typename F, typename S, typename TRUE_TY = void>153using EnableIfHasSignature = EnableIf<HasSignature<F, S>::value, TRUE_TY>;154155} // namespace traits156} // namespace dap157158#endif // dap_traits_h159160161