blob: 7df012481a3691f463041d82873ac44548f0aab0 [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
Ben Wagner230a71b2018-10-01 14:54:01 -040022#define SK_CALLABLE_TRAITS__COMMA ,
23
Ben Wagnerae3086e2018-12-04 13:05:20 -050024#define SK_CALLABLE_TRAITS__VARARGS(quals, _) \
25SK_CALLABLE_TRAITS__INSTANCE(quals,) \
Ben Wagner230a71b2018-10-01 14:54:01 -040026SK_CALLABLE_TRAITS__INSTANCE(quals, SK_CALLABLE_TRAITS__COMMA ...)
27
28#ifdef __cpp_noexcept_function_type
Ben Wagnerae3086e2018-12-04 13:05:20 -050029#define SK_CALLABLE_TRAITS__NE_VARARGS(quals, _) \
30SK_CALLABLE_TRAITS__VARARGS(quals,) \
31SK_CALLABLE_TRAITS__VARARGS(quals noexcept,)
Ben Wagner230a71b2018-10-01 14:54:01 -040032#else
Ben Wagnerae3086e2018-12-04 13:05:20 -050033#define SK_CALLABLE_TRAITS__NE_VARARGS(quals, _) \
34SK_CALLABLE_TRAITS__VARARGS(quals,)
Ben Wagner230a71b2018-10-01 14:54:01 -040035#endif
36
Ben Wagnerae3086e2018-12-04 13:05:20 -050037#define SK_CALLABLE_TRAITS__REF_NE_VARARGS(quals, _) \
38SK_CALLABLE_TRAITS__NE_VARARGS(quals,) \
39SK_CALLABLE_TRAITS__NE_VARARGS(quals &,) \
40SK_CALLABLE_TRAITS__NE_VARARGS(quals &&,)
Ben Wagner230a71b2018-10-01 14:54:01 -040041
42#define SK_CALLABLE_TRAITS__CV_REF_NE_VARARGS() \
Ben Wagnerae3086e2018-12-04 13:05:20 -050043SK_CALLABLE_TRAITS__REF_NE_VARARGS(,) \
44SK_CALLABLE_TRAITS__REF_NE_VARARGS(const,) \
45SK_CALLABLE_TRAITS__REF_NE_VARARGS(volatile,) \
46SK_CALLABLE_TRAITS__REF_NE_VARARGS(const volatile,)
Ben Wagner230a71b2018-10-01 14:54:01 -040047
48/** Infer the return_type and argument<N> of a callable type T. */
49template <typename T> struct SkCallableTraits : SkCallableTraits<decltype(&T::operator())> {};
50
51// function (..., (const, volatile), (&, &&), noexcept)
52#define SK_CALLABLE_TRAITS__INSTANCE(quals, varargs) \
53template <typename R, typename... Args> \
54struct SkCallableTraits<R(Args... varargs) quals> : sk_base_callable_traits<R, Args...> {};
55
56SK_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) \
61template <typename R, typename... Args> \
62struct SkCallableTraits<R(*)(Args... varargs) quals> : sk_base_callable_traits<R, Args...> {};
63
Ben Wagnerae3086e2018-12-04 13:05:20 -050064SK_CALLABLE_TRAITS__NE_VARARGS(,)
Ben Wagner230a71b2018-10-01 14:54:01 -040065#undef SK_CALLABLE_TRAITS__INSTANCE
66
67// pointer to method (..., (const, volatile), (&, &&), noexcept)
68#define SK_CALLABLE_TRAITS__INSTANCE(quals, varargs) \
69template <typename T, typename R, typename... Args> \
70struct SkCallableTraits<R(T::*)(Args... varargs) quals> : sk_base_callable_traits<R, Args...> {};
71
72SK_CALLABLE_TRAITS__CV_REF_NE_VARARGS()
73#undef SK_CALLABLE_TRAITS__INSTANCE
74
75// pointer to field
76template <typename T, typename R>
77struct 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
Ben Wagner230a71b2018-10-01 14:54:01 -040084
85#endif