FunctionTypeTraits.h (3941B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_FunctionTypeTraits_h 8 #define mozilla_FunctionTypeTraits_h 9 10 #include <cstddef> /* for size_t */ 11 12 namespace mozilla { 13 14 // Main FunctionTypeTraits declaration, taking one template argument. 15 // 16 // Given a function type, FunctionTypeTraits will expose the following members: 17 // - ReturnType: Return type. 18 // - arity: Number of parameters (size_t). 19 // - ParameterType<N>: Type of the Nth** parameter, 0-indexed. 20 // 21 // ** `ParameterType<N>` with `N` >= `arity` is allowed and gives `void`. 22 // This prevents compilation errors when trying to access a type outside of the 23 // function's parameters, which is useful for parameters checks, e.g.: 24 // template<typename F> 25 // auto foo(F&&) 26 // -> enable_if(FunctionTypeTraits<F>::arity == 1 && 27 // is_same<FunctionTypeTraits<F>::template ParameterType<0>, 28 // int>::value, 29 // void) 30 // { 31 // // This function will only be enabled if `F` takes one `int`. 32 // // Without the permissive ParameterType<any N>, it wouldn't even compile. 33 // 34 // Note: FunctionTypeTraits does not work with generic lambdas `[](auto&) {}`, 35 // because parameter types cannot be known until an actual invocation when types 36 // are inferred from the given arguments. 37 template <typename T> 38 struct FunctionTypeTraits; 39 40 // Remove reference and pointer wrappers, if any. 41 template <typename T> 42 struct FunctionTypeTraits<T&> : FunctionTypeTraits<T> {}; 43 template <typename T> 44 struct FunctionTypeTraits<T&&> : FunctionTypeTraits<T> {}; 45 template <typename T> 46 struct FunctionTypeTraits<T*> : FunctionTypeTraits<T> {}; 47 48 // Extract `operator()` function from callables (e.g. lambdas, std::function). 49 template <typename T> 50 struct FunctionTypeTraits : FunctionTypeTraits<decltype(&T::operator())> {}; 51 52 namespace detail { 53 template <size_t N, typename... As> 54 struct SafePackElement; 55 56 template <size_t N> 57 struct SafePackElement<N> { 58 using type = void; 59 }; 60 61 template <typename A, typename... As> 62 struct SafePackElement<0, A, As...> { 63 using type = A; 64 }; 65 66 template <size_t N, typename A, typename... As> 67 struct SafePackElement<N, A, As...> : SafePackElement<N - 1, As...> {}; 68 69 template <size_t N, typename... As> 70 using SafePackElementType = typename SafePackElement<N, As...>::type; 71 72 } // namespace detail 73 74 // Specialization for free functions. 75 template <typename R, typename... As> 76 struct FunctionTypeTraits<R(As...)> { 77 using ReturnType = R; 78 static constexpr size_t arity = sizeof...(As); 79 template <size_t N> 80 using ParameterType = detail::SafePackElementType<N, As...>; 81 }; 82 83 // Specialization for non-const member functions. 84 template <typename C, typename R, typename... As> 85 struct FunctionTypeTraits<R (C::*)(As...)> : FunctionTypeTraits<R(As...)> {}; 86 87 // Specialization for const member functions. 88 template <typename C, typename R, typename... As> 89 struct FunctionTypeTraits<R (C::*)(As...) const> 90 : FunctionTypeTraits<R(As...)> {}; 91 92 #ifdef NS_HAVE_STDCALL 93 // Specialization for __stdcall free functions. 94 template <typename R, typename... As> 95 struct FunctionTypeTraits<R NS_STDCALL(As...)> : FunctionTypeTraits<R(As...)> { 96 }; 97 98 // Specialization for __stdcall non-const member functions. 99 template <typename C, typename R, typename... As> 100 struct FunctionTypeTraits<R (NS_STDCALL C::*)(As...)> 101 : FunctionTypeTraits<R(As...)> {}; 102 103 // Specialization for __stdcall const member functions. 104 template <typename C, typename R, typename... As> 105 struct FunctionTypeTraits<R (NS_STDCALL C::*)(As...) const> 106 : FunctionTypeTraits<R(As...)> {}; 107 #endif // NS_HAVE_STDCALL 108 109 } // namespace mozilla 110 111 #endif // mozilla_FunctionTypeTraits_h