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 #include <tuple> 13 14 template <typename R, typename... Args> struct sk_base_callable_traits { 15 using return_type = R; 16 static constexpr std::size_t arity = sizeof...(Args); 17 template <std::size_t N> struct argument { 18 static_assert(N < arity, ""); 19 using type = typename std::tuple_element<N, std::tuple<Args...>>::type; 20 }; 21 }; 22 23 #define SK_CALLABLE_TRAITS__COMMA , 24 25 #define SK_CALLABLE_TRAITS__VARARGS(quals, _) \ 26 SK_CALLABLE_TRAITS__INSTANCE(quals,) \ 27 SK_CALLABLE_TRAITS__INSTANCE(quals, SK_CALLABLE_TRAITS__COMMA ...) 28 29 #ifdef __cpp_noexcept_function_type 30 #define SK_CALLABLE_TRAITS__NE_VARARGS(quals, _) \ 31 SK_CALLABLE_TRAITS__VARARGS(quals,) \ 32 SK_CALLABLE_TRAITS__VARARGS(quals noexcept,) 33 #else 34 #define SK_CALLABLE_TRAITS__NE_VARARGS(quals, _) \ 35 SK_CALLABLE_TRAITS__VARARGS(quals,) 36 #endif 37 38 #define SK_CALLABLE_TRAITS__REF_NE_VARARGS(quals, _) \ 39 SK_CALLABLE_TRAITS__NE_VARARGS(quals,) \ 40 SK_CALLABLE_TRAITS__NE_VARARGS(quals &,) \ 41 SK_CALLABLE_TRAITS__NE_VARARGS(quals &&,) 42 43 #define SK_CALLABLE_TRAITS__CV_REF_NE_VARARGS() \ 44 SK_CALLABLE_TRAITS__REF_NE_VARARGS(,) \ 45 SK_CALLABLE_TRAITS__REF_NE_VARARGS(const,) \ 46 SK_CALLABLE_TRAITS__REF_NE_VARARGS(volatile,) \ 47 SK_CALLABLE_TRAITS__REF_NE_VARARGS(const volatile,) 48 49 /** Infer the return_type and argument<N> of a callable type T. */ 50 template <typename T> struct SkCallableTraits : SkCallableTraits<decltype(&T::operator())> {}; 51 52 // function (..., (const, volatile), (&, &&), noexcept) 53 #define SK_CALLABLE_TRAITS__INSTANCE(quals, varargs) \ 54 template <typename R, typename... Args> \ 55 struct SkCallableTraits<R(Args... varargs) quals> : sk_base_callable_traits<R, Args...> {}; 56 57 SK_CALLABLE_TRAITS__CV_REF_NE_VARARGS() 58 #undef SK_CALLABLE_TRAITS__INSTANCE 59 60 // pointer to function (..., noexcept) 61 #define SK_CALLABLE_TRAITS__INSTANCE(quals, varargs) \ 62 template <typename R, typename... Args> \ 63 struct SkCallableTraits<R(*)(Args... varargs) quals> : sk_base_callable_traits<R, Args...> {}; 64 65 SK_CALLABLE_TRAITS__NE_VARARGS(,) 66 #undef SK_CALLABLE_TRAITS__INSTANCE 67 68 // pointer to method (..., (const, volatile), (&, &&), noexcept) 69 #define SK_CALLABLE_TRAITS__INSTANCE(quals, varargs) \ 70 template <typename T, typename R, typename... Args> \ 71 struct SkCallableTraits<R(T::*)(Args... varargs) quals> : sk_base_callable_traits<R, Args...> {}; 72 73 SK_CALLABLE_TRAITS__CV_REF_NE_VARARGS() 74 #undef SK_CALLABLE_TRAITS__INSTANCE 75 76 // pointer to field 77 template <typename T, typename R> 78 struct SkCallableTraits<R T::*> : sk_base_callable_traits<typename std::add_lvalue_reference<R>::type> {}; 79 80 #undef SK_CALLABLE_TRAITS__CV_REF_NE_VARARGS 81 #undef SK_CALLABLE_TRAITS__REF_NE_VARARGS 82 #undef SK_CALLABLE_TRAITS__NE_VARARGS 83 #undef SK_CALLABLE_TRAITS__VARARGS 84 #undef SK_CALLABLE_TRAITS__COMMA 85 86 #endif 87