blob: 9103bf2f4940fe3c26ca2307b854d66c0c89ed81 [file] [log] [blame]
Ben Wagner230a71b2018-10-01 14:54:01 -04001/*
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
13template <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__EMPTY
23#define SK_CALLABLE_TRAITS__COMMA ,
24
25#define SK_CALLABLE_TRAITS__VARARGS(quals) \
26SK_CALLABLE_TRAITS__INSTANCE(quals, SK_CALLABLE_TRAITS__EMPTY) \
27SK_CALLABLE_TRAITS__INSTANCE(quals, SK_CALLABLE_TRAITS__COMMA ...)
28
29#ifdef __cpp_noexcept_function_type
30#define SK_CALLABLE_TRAITS__NE_VARARGS(quals) \
31SK_CALLABLE_TRAITS__VARARGS(quals) \
32SK_CALLABLE_TRAITS__VARARGS(quals noexcept)
33#else
34#define SK_CALLABLE_TRAITS__NE_VARARGS(quals) \
35SK_CALLABLE_TRAITS__VARARGS(quals)
36#endif
37
38#define SK_CALLABLE_TRAITS__REF_NE_VARARGS(quals) \
39SK_CALLABLE_TRAITS__NE_VARARGS(quals) \
40SK_CALLABLE_TRAITS__NE_VARARGS(quals &) \
41SK_CALLABLE_TRAITS__NE_VARARGS(quals &&)
42
43#define SK_CALLABLE_TRAITS__CV_REF_NE_VARARGS() \
44SK_CALLABLE_TRAITS__REF_NE_VARARGS(SK_CALLABLE_TRAITS__EMPTY) \
45SK_CALLABLE_TRAITS__REF_NE_VARARGS(const) \
46SK_CALLABLE_TRAITS__REF_NE_VARARGS(volatile) \
47SK_CALLABLE_TRAITS__REF_NE_VARARGS(const volatile)
48
49/** Infer the return_type and argument<N> of a callable type T. */
50template <typename T> struct SkCallableTraits : SkCallableTraits<decltype(&T::operator())> {};
51
52// function (..., (const, volatile), (&, &&), noexcept)
53#define SK_CALLABLE_TRAITS__INSTANCE(quals, varargs) \
54template <typename R, typename... Args> \
55struct SkCallableTraits<R(Args... varargs) quals> : sk_base_callable_traits<R, Args...> {};
56
57SK_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) \
62template <typename R, typename... Args> \
63struct SkCallableTraits<R(*)(Args... varargs) quals> : sk_base_callable_traits<R, Args...> {};
64
65SK_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) \
70template <typename T, typename R, typename... Args> \
71struct SkCallableTraits<R(T::*)(Args... varargs) quals> : sk_base_callable_traits<R, Args...> {};
72
73SK_CALLABLE_TRAITS__CV_REF_NE_VARARGS()
74#undef SK_CALLABLE_TRAITS__INSTANCE
75
76// pointer to field
77template <typename T, typename R>
78struct 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#undef SK_CALLABLE_TRAITS__EMPTY
86
87#endif