/* * Copyright 2018 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef SkCallableTraits_DEFINED #define SkCallableTraits_DEFINED #include #include template struct sk_base_callable_traits { using return_type = R; static constexpr std::size_t arity = sizeof...(Args); template struct argument { static_assert(N < arity, ""); using type = typename std::tuple_element>::type; }; }; #define SK_CALLABLE_TRAITS__COMMA , #define SK_CALLABLE_TRAITS__VARARGS(quals, _) \ SK_CALLABLE_TRAITS__INSTANCE(quals,) \ SK_CALLABLE_TRAITS__INSTANCE(quals, SK_CALLABLE_TRAITS__COMMA ...) #ifdef __cpp_noexcept_function_type #define SK_CALLABLE_TRAITS__NE_VARARGS(quals, _) \ SK_CALLABLE_TRAITS__VARARGS(quals,) \ SK_CALLABLE_TRAITS__VARARGS(quals noexcept,) #else #define SK_CALLABLE_TRAITS__NE_VARARGS(quals, _) \ SK_CALLABLE_TRAITS__VARARGS(quals,) #endif #define SK_CALLABLE_TRAITS__REF_NE_VARARGS(quals, _) \ SK_CALLABLE_TRAITS__NE_VARARGS(quals,) \ SK_CALLABLE_TRAITS__NE_VARARGS(quals &,) \ SK_CALLABLE_TRAITS__NE_VARARGS(quals &&,) #define SK_CALLABLE_TRAITS__CV_REF_NE_VARARGS() \ SK_CALLABLE_TRAITS__REF_NE_VARARGS(,) \ SK_CALLABLE_TRAITS__REF_NE_VARARGS(const,) \ SK_CALLABLE_TRAITS__REF_NE_VARARGS(volatile,) \ SK_CALLABLE_TRAITS__REF_NE_VARARGS(const volatile,) /** Infer the return_type and argument of a callable type T. */ template struct SkCallableTraits : SkCallableTraits {}; // function (..., (const, volatile), (&, &&), noexcept) #define SK_CALLABLE_TRAITS__INSTANCE(quals, varargs) \ template \ struct SkCallableTraits : sk_base_callable_traits {}; SK_CALLABLE_TRAITS__CV_REF_NE_VARARGS() #undef SK_CALLABLE_TRAITS__INSTANCE // pointer to function (..., noexcept) #define SK_CALLABLE_TRAITS__INSTANCE(quals, varargs) \ template \ struct SkCallableTraits : sk_base_callable_traits {}; SK_CALLABLE_TRAITS__NE_VARARGS(,) #undef SK_CALLABLE_TRAITS__INSTANCE // pointer to method (..., (const, volatile), (&, &&), noexcept) #define SK_CALLABLE_TRAITS__INSTANCE(quals, varargs) \ template \ struct SkCallableTraits : sk_base_callable_traits {}; SK_CALLABLE_TRAITS__CV_REF_NE_VARARGS() #undef SK_CALLABLE_TRAITS__INSTANCE // pointer to field template struct SkCallableTraits : sk_base_callable_traits::type> {}; #undef SK_CALLABLE_TRAITS__CV_REF_NE_VARARGS #undef SK_CALLABLE_TRAITS__REF_NE_VARARGS #undef SK_CALLABLE_TRAITS__NE_VARARGS #undef SK_CALLABLE_TRAITS__VARARGS #undef SK_CALLABLE_TRAITS__COMMA #endif