1 /* 2 * Copyright 2018 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef SkCallableTraits_DEFINED 9 #define SkCallableTraits_DEFINED 10 11 #include <type_traits> 12 13 template <typename R, typename... Args> struct sk_base_callable_traits { 14 using return_type = R; 15 static constexpr std::size_t arity = sizeof...(Args); 16 template <std::size_t N> struct argument { 17 static_assert(N < arity, ""); 18 using type = typename std::tuple_element<N, std::tuple<Args...>>::type; 19 }; 20 }; 21 22 #define SK_CALLABLE_TRAITS__COMMA , 23 24 #define SK_CALLABLE_TRAITS__VARARGS(quals, _) \ 25 SK_CALLABLE_TRAITS__INSTANCE(quals,) \ 26 SK_CALLABLE_TRAITS__INSTANCE(quals, SK_CALLABLE_TRAITS__COMMA ...) 27 28 #ifdef __cpp_noexcept_function_type 29 #define SK_CALLABLE_TRAITS__NE_VARARGS(quals, _) \ 30 SK_CALLABLE_TRAITS__VARARGS(quals,) \ 31 SK_CALLABLE_TRAITS__VARARGS(quals noexcept,) 32 #else 33 #define SK_CALLABLE_TRAITS__NE_VARARGS(quals, _) \ 34 SK_CALLABLE_TRAITS__VARARGS(quals,) 35 #endif 36 37 #define SK_CALLABLE_TRAITS__REF_NE_VARARGS(quals, _) \ 38 SK_CALLABLE_TRAITS__NE_VARARGS(quals,) \ 39 SK_CALLABLE_TRAITS__NE_VARARGS(quals &,) \ 40 SK_CALLABLE_TRAITS__NE_VARARGS(quals &&,) 41 42 #define SK_CALLABLE_TRAITS__CV_REF_NE_VARARGS() \ 43 SK_CALLABLE_TRAITS__REF_NE_VARARGS(,) \ 44 SK_CALLABLE_TRAITS__REF_NE_VARARGS(const,) \ 45 SK_CALLABLE_TRAITS__REF_NE_VARARGS(volatile,) \ 46 SK_CALLABLE_TRAITS__REF_NE_VARARGS(const volatile,) 47 48 /** Infer the return_type and argument<N> of a callable type T. */ 49 template <typename T> struct SkCallableTraits : SkCallableTraits<decltype(&T::operator())> {}; 50 51 // function (..., (const, volatile), (&, &&), noexcept) 52 #define SK_CALLABLE_TRAITS__INSTANCE(quals, varargs) \ 53 template <typename R, typename... Args> \ 54 struct SkCallableTraits<R(Args... varargs) quals> : sk_base_callable_traits<R, Args...> {}; 55 56 SK_CALLABLE_TRAITS__CV_REF_NE_VARARGS() 57 #undef SK_CALLABLE_TRAITS__INSTANCE 58 59 // pointer to function (..., noexcept) 60 #define SK_CALLABLE_TRAITS__INSTANCE(quals, varargs) \ 61 template <typename R, typename... Args> \ 62 struct SkCallableTraits<R(*)(Args... varargs) quals> : sk_base_callable_traits<R, Args...> {}; 63 64 SK_CALLABLE_TRAITS__NE_VARARGS(,) 65 #undef SK_CALLABLE_TRAITS__INSTANCE 66 67 // pointer to method (..., (const, volatile), (&, &&), noexcept) 68 #define SK_CALLABLE_TRAITS__INSTANCE(quals, varargs) \ 69 template <typename T, typename R, typename... Args> \ 70 struct SkCallableTraits<R(T::*)(Args... varargs) quals> : sk_base_callable_traits<R, Args...> {}; 71 72 SK_CALLABLE_TRAITS__CV_REF_NE_VARARGS() 73 #undef SK_CALLABLE_TRAITS__INSTANCE 74 75 // pointer to field 76 template <typename T, typename R> 77 struct SkCallableTraits<R T::*> : sk_base_callable_traits<typename std::add_lvalue_reference<R>::type> {}; 78 79 #undef SK_CALLABLE_TRAITS__CV_REF_NE_VARARGS 80 #undef SK_CALLABLE_TRAITS__REF_NE_VARARGS 81 #undef SK_CALLABLE_TRAITS__NE_VARARGS 82 #undef SK_CALLABLE_TRAITS__VARARGS 83 #undef SK_CALLABLE_TRAITS__COMMA 84 85 #endif 86