• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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