| /* |
| * 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 <type_traits> |
| #include <tuple> |
| |
| template <typename R, typename... Args> struct sk_base_callable_traits { |
| using return_type = R; |
| static constexpr std::size_t arity = sizeof...(Args); |
| template <std::size_t N> struct argument { |
| static_assert(N < arity, ""); |
| using type = typename std::tuple_element<N, std::tuple<Args...>>::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<N> of a callable type T. */ |
| template <typename T> struct SkCallableTraits : SkCallableTraits<decltype(&T::operator())> {}; |
| |
| // function (..., (const, volatile), (&, &&), noexcept) |
| #define SK_CALLABLE_TRAITS__INSTANCE(quals, varargs) \ |
| template <typename R, typename... Args> \ |
| struct SkCallableTraits<R(Args... varargs) quals> : sk_base_callable_traits<R, Args...> {}; |
| |
| SK_CALLABLE_TRAITS__CV_REF_NE_VARARGS() |
| #undef SK_CALLABLE_TRAITS__INSTANCE |
| |
| // pointer to function (..., noexcept) |
| #define SK_CALLABLE_TRAITS__INSTANCE(quals, varargs) \ |
| template <typename R, typename... Args> \ |
| struct SkCallableTraits<R(*)(Args... varargs) quals> : sk_base_callable_traits<R, Args...> {}; |
| |
| SK_CALLABLE_TRAITS__NE_VARARGS(,) |
| #undef SK_CALLABLE_TRAITS__INSTANCE |
| |
| // pointer to method (..., (const, volatile), (&, &&), noexcept) |
| #define SK_CALLABLE_TRAITS__INSTANCE(quals, varargs) \ |
| template <typename T, typename R, typename... Args> \ |
| struct SkCallableTraits<R(T::*)(Args... varargs) quals> : sk_base_callable_traits<R, Args...> {}; |
| |
| SK_CALLABLE_TRAITS__CV_REF_NE_VARARGS() |
| #undef SK_CALLABLE_TRAITS__INSTANCE |
| |
| // pointer to field |
| template <typename T, typename R> |
| struct SkCallableTraits<R T::*> : sk_base_callable_traits<typename std::add_lvalue_reference<R>::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 |